From 05b75b6266d128541f3356a2497c26d31d1baf3b Mon Sep 17 00:00:00 2001 From: Robert Knight Date: Thu, 18 Sep 2025 13:53:28 +0100 Subject: [PATCH] Remove Tailwind JS config Going forwards downstream projects must use CSS-based config instead, which is the preferred method in Tailwind v4. --- README.md | 25 ++--- package.json | 1 - src/tailwind.focus-visible-ring.js | 64 ----------- src/tailwind.preset.js | 172 ----------------------------- src/tailwind.scroll-shadows.js | 64 ----------- styles/test.css | 6 +- tailwind.config.js | 47 -------- 7 files changed, 12 insertions(+), 367 deletions(-) delete mode 100644 src/tailwind.focus-visible-ring.js delete mode 100644 src/tailwind.preset.js delete mode 100644 src/tailwind.scroll-shadows.js delete mode 100644 tailwind.config.js diff --git a/README.md b/README.md index a581da48d..aa76c4a15 100644 --- a/README.md +++ b/README.md @@ -7,26 +7,21 @@ UI components for Hypothesis front-end applications. Your project must have `preact` and `tailwindcss` as dependencies. ```sh -$ yarn add preact tailwindcss +$ yarn add preact tailwindcss @tailwindcss/postcss $ yarn add @hypothesis/frontend-shared ``` -### tailwindcss configuration +In your project's CSS entry point, add a `@source` for the frontend-shared +package and import the Tailwind theme: -Update your project's tailwind configuration: +```css +@import 'tailwindcss' source(none); -```js -import tailwindConfig from '@hypothesis/frontend-shared/lib/tailwind.preset.js'; - -export default { - // Use this package's preset - presets: [tailwindConfig], - content: [ - // Be sure to add this project's component source to your - // tailwind content globs - './node_modules/@hypothesis/frontend-shared/lib/**/*.{js,ts,tsx}', - ], - // ... +/* Configure source files to scan for Tailwind classes. */ +@source './node_modules/@hypothesis/frontend-shared/lib/**/*.js'; + +/* Import theme and utilities from shared package. */ +@import '@hypothesis/frontend-shared/tailwind-config.css'; ``` ## Documentation diff --git a/package.json b/package.json index 5bbb37582..7898ecb21 100644 --- a/package.json +++ b/package.json @@ -91,7 +91,6 @@ "exports": { ".": "./lib/index.js", "./pattern-library": "./lib/pattern-library/index.js", - "./tailwind.preset.js": "./lib/tailwind.preset.js", "./tailwind-config.css": "./src/tailwind-config.css" }, "browserslist": "chrome 70, firefox 70, safari 11.1", diff --git a/src/tailwind.focus-visible-ring.js b/src/tailwind.focus-visible-ring.js deleted file mode 100644 index ab767ac82..000000000 --- a/src/tailwind.focus-visible-ring.js +++ /dev/null @@ -1,64 +0,0 @@ -import plugin from 'tailwindcss/plugin.js'; - -/** - * Provide the `.focus-visible-ring` utility class. - * - * Add a utility class that will render a focus ring on a focused element - * only when it has keyboard focus, or otherwise has `:focus-visible`. Do not - * show a focus ring if the element has focus but is not `:focus-visible`. - * - * This plugin should only be necessary until such a time that we feel browser - * support for :focus-visible is acceptable. At that time, what this plugin - * does should be achievable with a few standard tailwind utility classes. - * - * This styling requires the browser to support the :focus-visible - * pseudo-selector [1] or for the JS polyfill [2] to be loaded. - * - * [1] https://developer.mozilla.org/en-US/docs/Web/CSS/:focus-visible - * [2] https://github.com/WICG/focus-visible - * - * This can be combined with other Tailwind utility classes to customize. - * Example Usage: - * - - * Show a focus-visible ring in the theme's `ringColor` - * - - * Same as above, but explicitly inset - * - - * Set ring shadow offset - * - - * Set ring color - * - * Ring width is this theme's `ringWidth.DEFAULT` - */ - -/** @type {any} */ -export const focusVisibleRing = plugin(({ addUtilities, theme }) => { - const ringWidth = theme('ringWidth.DEFAULT'); - // Based on TW ring/shadow rules https://tailwindcss.com/docs/ring-width - const focusRing = `var(--tw-ring-inset) 0 0 0 calc(${ringWidth} + var(--tw-ring-offset-width)) var(--tw-ring-color)`; - - addUtilities({ - '.focus-visible-ring': { - // 1. set a visible focus ring if this element has focus (fallback) - '&:focus': { - boxShadow: focusRing, - outline: 'none', - }, - // 2. set a visible focus ring if this element has `:focus-visible` - '&:focus-visible': { - boxShadow: focusRing, - outline: 'none', - }, - // 3. Remove focus ring if element is focused but does not have - // `:focus-visible` (in browsers that support `:focus-visible`) - '&:focus:not(:focus-visible)': { - boxShadow: 'none', - }, - // 4. Remove focus ring if element is focused but does not have - // a focus-visible class set by the polyfill - '.js-focus-visible &:focus:not(.focus-visible)': { - boxShadow: 'none', - }, - }, - }); -}); diff --git a/src/tailwind.preset.js b/src/tailwind.preset.js deleted file mode 100644 index 017874721..000000000 --- a/src/tailwind.preset.js +++ /dev/null @@ -1,172 +0,0 @@ -import colors from 'tailwindcss/colors.js'; -import plugin from 'tailwindcss/plugin.js'; - -import { focusVisibleRing } from './tailwind.focus-visible-ring.js'; -import { scrollShadows } from './tailwind.scroll-shadows.js'; - -// Equivalent to spacing value 11; minimum touch-target size -const minimumTouchDimension = '44px'; - -// Default colors -const green = '#00a36d'; -const yellow = '#fbc168'; -const red = '#d93c3f'; - -export default /** @type {Partial} */ ({ - theme: { - extend: { - animation: { - 'fade-in': 'fade-in 0.3s forwards', - 'fade-out': 'fade-out 0.3s forwards', - }, - borderColor: { - DEFAULT: '#dbdbdb', - }, - boxShadow: { - DEFAULT: '0 1px 1px rgba(0, 0, 0, 0.1)', - md: '0px 2px 3px 0px rgba(0, 0, 0, 0.15)', - }, - colors: { - transparent: 'transparent', - current: 'currentColor', - white: colors.white, - black: colors.black, - grey: { - 0: '#fafafa', - 1: '#f2f2f2', - 2: '#ececec', - 3: '#dbdbdb', - 4: '#a6a6a6', - 5: '#9c9c9c', - 6: '#737373', - 7: '#595959', - 8: '#3f3f3f', - 9: '#202020', - }, - slate: { - 0: '#f4f4f6', - 1: '#e3e3e5', - 3: '#babac4', - 5: '#9c9cab', - 7: '#575768', - 9: '#131316', - }, - blue: { - focus: '#59a7e8', - }, - green: { - light: '#dfebe7', - DEFAULT: green, - dark: '#005c3d', - success: green, - }, - yellow: { - light: '#fef7ec', - DEFAULT: yellow, - dark: '#774903', - notice: yellow, - }, - red: { - light: '#f0e2e3', - DEFAULT: red, - dark: '#891b1d', - error: red, - }, - brand: { - dark: '#84141e', - DEFAULT: '#bd1c2b', - }, - // This naming makes color-related classnames generated from this - // token less ambiguous. e.g. `bg-color-text` instead of `bg-text` - 'color-text': { - DEFAULT: '#202020', - light: '#737373', - inverted: '#f2f2f2', - }, - }, - fontSize: { - // Set font size to the maximum of 16px and the inherited size. - // - // On iOS, the input font size must be at least 16px to prevent the - // browser from zooming into it on touch. - 'at-least-16px': 'max(16px, 100%)', - }, - keyframes: { - 'fade-in': { - '0%': { - opacity: '0', - }, - '100%': { - opacity: '1', - }, - }, - 'fade-out': { - '0%': { - opacity: '1', - }, - '100%': { - opacity: '0', - }, - }, - }, - minHeight: { - 'touch-minimum': minimumTouchDimension, - }, - minWidth: { - 'touch-minimum': minimumTouchDimension, - }, - ringColor: { - DEFAULT: '#59a7e8', - }, - ringOpacity: { - // Tailwind's default ring opacity is `0.5` - DEFAULT: '1.0', - }, - ringWidth: { - DEFAULT: '2px', - }, - screens: { - tall: { raw: '(min-height: 32rem)' }, - touch: { raw: '(pointer: coarse)' }, - }, - spacing: { - em: '1em', - '2em': '2em', - '4em': '4em', - 'touch-minimum': minimumTouchDimension, - }, - zIndex: { - 1: '1', - 2: '2', - 3: '3', - 4: '4', - 5: '5', - 10: '10', - max: '2147483647', - }, - }, - }, - plugins: [ - // Make `.focus-visible-ring` an available utility class - focusVisibleRing, - // Add `.scroll-shadows` for use by Scroll components - scrollShadows, - plugin(({ addVariant }) => { - // Add a custom variant to mark an element to serve as a container for - // a set of grouped input components. This is the same functionality - // as Tailwind's built-in "group" variant, but with a different name for - // clarity of purpose. - // See https://tailwindcss.com/docs/hover-focus-and-other-states#styling-based-on-parent-state - addVariant('input-group', '.input-group &'); - }), - plugin(({ addUtilities }) => { - addUtilities({ - // Tailwind v3 does not provide this specific break utility: https://v3.tailwindcss.com/docs/word-break - // Tailwind v4 does have an equivalent utility that we can eventually adopt https://tailwindcss.com/docs/overflow-wrap#wrapping-anywhere - '.hyp-wrap-anywhere': { - 'overflow-wrap': 'anywhere', - }, - }); - }), - ], -}); diff --git a/src/tailwind.scroll-shadows.js b/src/tailwind.scroll-shadows.js deleted file mode 100644 index 9bd79d1fd..000000000 --- a/src/tailwind.scroll-shadows.js +++ /dev/null @@ -1,64 +0,0 @@ -import plugin from 'tailwindcss/plugin.js'; - -/** - * Utility class to show scroll-hint shadows at the top and bottom of a - * scrollable frame element if: - * - The content height exceeds the frame height: i.e. can be scrolled, and - * - The content is scrollable in the shadow's direction (up or down) - * - * Shadows are not visible once the frame has been scrolled all the way in the - * shadow's direction. Shadows are not visible if the height of the content - * does not overflow the frame (is not scrollable). - * - * The shadow hinting is handled by four positioned background gradients: - * - One gradient each at top and bottom of frame that obscure the shadow hints - * (shadow covers). These use `background-attachment: local`, which makes - * their position fixed to the _content_ within the scrollbox. - * - One gradient each at the top and the bottom of the frame that are the - * shadow hints (shadows). These use `background-attachment: scroll` such - * that they are always positioned at the top and the bottom of the - * _scrollbox_ frame. When these positions align with the positions of the - * shadow covers--at the top and the bottom of the overflowing content-- - * they will be obscured by those shadow covers. - * - * See https://lea.verou.me/2012/04/background-attachment-local/ - * - * Safari's behavior can be different because of a bug with - * `background-attachment: local`. - * See https://bugs.webkit.org/show_bug.cgi?id=219324 - * In Safari < 15.4: - * - Scroll-hint shadows do not appear if content does not overflow (this is - * consistent with other browsers) - * - Only the bottom scroll-hint shadow appears if content overflows - * - The bottom scroll-hint shadow is always present, even if content is - * fully scrolled - */ - -/** @type {any} */ -export const scrollShadows = plugin(({ addUtilities }) => { - // These "shadow covers" scroll with the content. They align with and - // obscure the shadows when an element is scrolled all the way in one - // direction. If there is no overflow (nothing to scroll), these covers keep - // any shadows from showing. - const topShadowCover = - 'linear-gradient(white 30%, rgba(255, 255, 255, 0)) 0 0'; - const bottomShadowCover = - 'linear-gradient(rgba(255, 255, 255, 0), white 70%) 0 100%'; - - // The shadows are in a fixed position (`background-attachment: scroll`) - // relative to the scrolling container. - const topShadow = - 'linear-gradient(to bottom, rgba(0, 0, 0, 0.1), rgba(0, 0, 0, 0.05) 5px, rgba(255, 255, 255, 0) 70%) 0 0'; - const bottomShadow = - 'linear-gradient(to top, rgba(0, 0, 0, 0.1), rgba(0, 0, 0, 0.05) 5px, rgba(255, 255, 255, 0) 70%) 0 100%'; - - addUtilities({ - '.scroll-shadows': { - background: `${topShadowCover}, ${bottomShadowCover}, ${topShadow}, ${bottomShadow}`, - backgroundRepeat: 'no-repeat', - backgroundColor: 'white', - backgroundSize: '100% 40px, 100% 40px, 100% 14px, 100% 14px', - backgroundAttachment: 'local, local, scroll, scroll', - }, - }); -}); diff --git a/styles/test.css b/styles/test.css index d53270039..12b5c2dac 100644 --- a/styles/test.css +++ b/styles/test.css @@ -1,6 +1,4 @@ -/** - * Stylesheet for tests - */ +/* Stylesheet for tests. */ @import 'tailwindcss'; -@config '../tailwind.config.js'; +@import '../src/tailwind-config.css'; diff --git a/tailwind.config.js b/tailwind.config.js deleted file mode 100644 index 94aaed2bf..000000000 --- a/tailwind.config.js +++ /dev/null @@ -1,47 +0,0 @@ -/** - * Tailwind configuration for local pattern library styles - */ -import tailwindPreset from './src/tailwind.preset.js'; - -export default { - presets: [tailwindPreset], - content: ['./src/**/*.{js,ts,tsx}', './templates/**/*.html'], - - // Pattern library specific config - theme: { - extend: { - animation: { - 'slide-in-from-right': 'slide-in-from-right 0.3s forwards ease-in-out', - 'slide-out-to-right': 'slide-out-to-right 0.3s forwards ease-in-out', - }, - keyframes: { - 'slide-in-from-right': { - '0%': { - opacity: '0', - left: '100%', - }, - '80%': { - left: '-10px', - }, - '100%': { - left: '0', - opacity: '1', - }, - }, - 'slide-out-to-right': { - '0%': { - left: '0', - opacity: '1', - }, - '20%': { - left: '-10px', - }, - '100%': { - opacity: '0', - left: '100%', - }, - }, - }, - }, - }, -};