Skip to content

feat: Add max-width container query support #35

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
56 changes: 51 additions & 5 deletions src/index.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,33 @@
import plugin from 'tailwindcss/plugin'

type ContainerValue = string | { min?: string; max?: string }
type QueryType = 'min-width' | 'max-width'

export = plugin(
function containerQueries({ matchUtilities, matchVariant, theme }) {
let values: Record<string, string> = theme('containers') ?? {}
let values: Record<string, ContainerValue> = theme('containers') ?? {}

// Process the container values to support both string and object formats
let processedValues: Record<string, string> = {}
let queryTypes: Record<string, QueryType> = {}

// Transform the theme values into a format we can use
for (const [key, value] of Object.entries(values)) {
if (typeof value === 'string') {
// String value - use as min-width (original behavior)
processedValues[key] = value
queryTypes[key] = 'min-width'
} else if (typeof value === 'object' && value !== null) {
// Object with min/max properties
if (value.min) {
processedValues[key] = value.min
queryTypes[key] = 'min-width'
} else if (value.max) {
processedValues[key] = value.max
queryTypes[key] = 'max-width'
}
}
}

function parseValue(value: string) {
let numericValue = value.match(/^(\d+\.\d+|\d+|\.\d+)\D+/)?.[1] ?? null
Expand Down Expand Up @@ -34,18 +59,39 @@ export = plugin(
(value = '', { modifier }) => {
let parsed = parseValue(value)

return parsed !== null ? `@container ${modifier ?? ''} (min-width: ${value})` : []
// Find the key for this value to determine query type
const key = Object.keys(processedValues).find(k => processedValues[k] === value)
const queryType = key ? queryTypes[key] : 'min-width'

return parsed !== null ? `@container ${modifier ?? ''} (${queryType}: ${value})` : []
},
{
values,
values: processedValues,
sort(aVariant, zVariant) {
let a = parseFloat(aVariant.value)
let z = parseFloat(zVariant.value)

if (a === null || z === null) return 0

// Sort values themselves regardless of unit
if (a - z !== 0) return a - z
// Find keys to determine query types
const aKey = Object.keys(processedValues).find(k => processedValues[k] === aVariant.value)
const zKey = Object.keys(processedValues).find(k => processedValues[k] === zVariant.value)

const aType = aKey ? queryTypes[aKey] : 'min-width'
const zType = zKey ? queryTypes[zKey] : 'min-width'

// If they have different types, sort max-width first
if (aType !== zType) {
return aType === 'max-width' ? -1 : 1
}

// For max-width queries, we want descending order
if (aType === 'max-width') {
if (a - z !== 0) return z - a
} else {
// Original sort logic for min-width
if (a - z !== 0) return a - z
}

let aLabel = aVariant.modifier ?? ''
let zLabel = zVariant.modifier ?? ''
Expand Down