Repository: tailwindlabs/tailwindcss (TypeScript)
Task: Feature (2018-05-08 10:02:22+00:00)

Issue:
Feature Proposal: Add :focus-within @variant
I'd be useful to have a `:focus-within` variant, for better styling control in forms.

Functionality-wise, it'd work exactly the same has `focus`, `active`, and `hover`, as its rules would too follow the structure `.[variant-name]:[class-name]:[variant-name]`, with no side-effects.


Discussion:
If I'm not mistaken, this’d only imply changes in these two:

https://github.com/tailwindcss/tailwindcss/blob/0f0a4f45e8e2122e99850d11ad2c576be249e366/src/lib/substituteVariantsAtRules.js#L21-L34

https://github.com/tailwindcss/tailwindcss/blob/0f0a4f45e8e2122e99850d11ad2c576be249e366/src/lib/substituteVariantsAtRules.js#L51-L55

…plus the corresponding [tests](https://github.com/tailwindcss/tailwindcss/blob/0f0a4f45e8e2122e99850d11ad2c576be249e366/__tests__/variantsAtRule.test.js), correct?

If so, I can surely contribute those changes, if there’s a go-ahead from the core team on the feature.

Patch:
diff --git a/defaultConfig.stub.js b/defaultConfig.stub.js
--- a/defaultConfig.stub.js
+++ b/defaultConfig.stub.js
@@ -852,6 +852,7 @@ module.exports = {
   |   - responsive
   |   - hover
   |   - focus
+  |   - focus-within
   |   - active
   |   - group-hover
   |
diff --git a/src/lib/substituteVariantsAtRules.js b/src/lib/substituteVariantsAtRules.js
--- a/src/lib/substituteVariantsAtRules.js
+++ b/src/lib/substituteVariantsAtRules.js
@@ -17,6 +17,7 @@ const defaultVariantGenerators = {
     })
   }),
   hover: generatePseudoClassVariant('hover'),
+  'focus-within': generatePseudoClassVariant('focus-within'),
   focus: generatePseudoClassVariant('focus'),
   active: generatePseudoClassVariant('active'),
 }
@@ -44,7 +45,7 @@ export default function(config, { variantGenerators: pluginVariantGenerators })
           variantGenerators[variant](atRule, config)
         })
       } else {
-        _.forEach(['group-hover', 'hover', 'focus', 'active'], variant => {
+        _.forEach(['group-hover', 'hover', 'focus-within', 'focus', 'active'], variant => {
           if (variants.includes(variant)) {
             variantGenerators[variant](atRule, config)
           }


Test patch:
diff --git a/__tests__/variantsAtRule.test.js b/__tests__/variantsAtRule.test.js
--- a/__tests__/variantsAtRule.test.js
+++ b/__tests__/variantsAtRule.test.js
@@ -70,6 +70,27 @@ test('it can generate focus variants', () => {
   })
 })
 
+test('it can generate focus-within variants', () => {
+  const input = `
+    @variants focus-within {
+      .banana { color: yellow; }
+      .chocolate { color: brown; }
+    }
+  `
+
+  const output = `
+      .banana { color: yellow; }
+      .chocolate { color: brown; }
+      .focus-within\\:banana:focus-within { color: yellow; }
+      .focus-within\\:chocolate:focus-within { color: brown; }
+  `
+
+  return run(input).then(result => {
+    expect(result.css).toMatchCss(output)
+    expect(result.warnings().length).toBe(0)
+  })
+})
+
 test('it can generate group-hover variants', () => {
   const input = `
     @variants group-hover {