Skip to content
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

Add @container query support to the createTextStyle function #147

Open
wants to merge 5 commits into
base: master
Choose a base branch
from

Conversation

plexey
Copy link

@plexey plexey commented Sep 17, 2023

Thanks for providing the @capsizecss/vanilla-extract package - it makes generating and consuming capsized text styles in a vanilla-extract project very easy.

I was recently trying to size text based on the container it's in with a @container query and noticed this isn't supported like @media queries are. Rather than opening an issue I decided to make the change myself, but I'm happy to make an issue instead if you'd prefer.


This is a PR to add @container query support to the createTextStyle function from the @capsizecss/vanilla-extract package.

createTextStyle already supports @media queries, accepting a vanilla-extract media query object as a second argument like so:

export const text = createTextStyle(textDefinitions.mobile, {
  '@media': {
    'screen and (min-width: 768px)': textDefinitions.tablet,
    'screen and (min-width: 1024px)': textDefinitions.desktop,
  },
});

This PR extends createTextStyle so that you can also provide a vanilla-extract container query object as the second argument like so:

import { style, createContainer } from '@vanilla-extract/css';

const containerName = createContainer();

export const container = style({
  containerName,
  containerType: 'inline-size',
  outline: 'solid 1px blue',
});

export const containerText = createTextStyle(textValues.mobile, {
  '@container': {
    [`${containerName} (min-width: 768px)`]: textValues.tablet,
    [`${containerName} (min-width: 1024px)`]: textValues.desktop,
  },
});

I've added a basic story to vanilla-extract Storybook named Container that provides a visual demonstration of the container based behaviour:

image

The blue outlines around each text row delimits the width of the containers wrapping each text row.

This is to indicate that the text within each container responds to the width of the container.

As mentioned, I'd be happy to open an issue instead, but thought I'd have a crack at adding @container support first.

@plexey plexey requested a review from a team as a code owner September 17, 2023 12:07
Copy link
Contributor

@michaeltaranto michaeltaranto left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for making this PR. Added a few comments below

[`${containerName} (min-width: 600px)`]: textValues.desktop,
},
},
'responsiveText',
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's align the debugId here:

Suggested change
'responsiveText',
'containerText',

queryType,
queries,
}: {
queryType: '@media' | '@container';
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thoughts on extracting this from the type?

Suggested change
queryType: '@media' | '@container';
queryType: keyof ConditionalQueries;

[350, 550, 700]
.map(
(width) => `
<div style="width: ${width}px;" class="${styles.container}">
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These should probably use a max-width:

Suggested change
<div style="width: ${width}px;" class="${styles.container}">
<div style="width: 100%; max-width: ${width}px;" class="${styles.container}">

At the moment they seem to just grow and never conditionally adapt.

Comment on lines +24 to +35
const queryVars: StyleRule[typeof queryType] = {};

Object.entries(queries).forEach(([query, value]) => {
const builtValues =
'capHeightTrim' in value
? (value as ComputedValues)
: precomputeValues(value);

queryVars[query] = { vars: assignVars(capsizeVars, builtValues) };
});

return queryVars;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can i suggest renaming queryVars to queryRule given it is generating the ruleset:

Suggested change
const queryVars: StyleRule[typeof queryType] = {};
Object.entries(queries).forEach(([query, value]) => {
const builtValues =
'capHeightTrim' in value
? (value as ComputedValues)
: precomputeValues(value);
queryVars[query] = { vars: assignVars(capsizeVars, builtValues) };
});
return queryVars;
const queryRule: StyleRule[typeof queryType] = {};
Object.entries(queries).forEach(([query, value]) => {
const builtValues =
'capHeightTrim' in value
? (value as ComputedValues)
: precomputeValues(value);
queryRule[query] = { vars: assignVars(capsizeVars, builtValues) };
});
return queryRule;

That would go for the function too, generateQueryVars to generateQueryRule.


(I noticed this is likely extending something that was my fault, in createVanillaStyle we build up a vars variable, which is actually a "styleRule". You can update that for bonus points 😄)

@@ -137,6 +137,8 @@ export const text = createTextStyle(vars.bodyText.mobile, {
});
```

As an alternative to passing a media query object, can also provide a vanilla-extract [container query object](https://vanilla-extract.style/documentation/styling/#container-queries).
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Small typo, but you're probably under selling it here too, i'd add an example!

Suggested change
As an alternative to passing a media query object, can also provide a vanilla-extract [container query object](https://vanilla-extract.style/documentation/styling/#container-queries).
#### Container queries
Queries can be provided following the vanilla-extract [container query object syntax](https://vanilla-extract.style/documentation/styling/#container-queries). For example:
```ts
// Text.css.ts
import { createTheme, createContainer } from '@vanilla-extract/css';
import { createTextStyle, precomputeValues } from '@capsizecss/vanilla-extract';
const containerName = createContainer();
const [themeClass, vars] = createTheme({
bodyText: {
small: precomputeValues({ fontSize: 14, leading: 18, fontMetrics }),
medium: precomputeValues({ fontSize: 16, leading: 22, fontMetrics }),
large: precomputeValues({ fontSize: 18, leading: 24, fontMetrics }),
},
});
export const containerText = createTextStyle(vars.bodyText.small, {
'@container': {
[`${containerName} (min-width: 400px)`]: vars.bodyText.medium,
[`${containerName} (min-width: 600px)`]: vars.bodyText.large,
},
});
```

Would you mind re-wording the intro to this section too?

Responsive typography

As a convenience for responsive styles, createTextStyle accepts a second argument in the form of conditional vanillia-extract styling queries, returning a responsive class list.

Media queries

Queries can be provided following the vanilla-extract media query object syntax. For example:

Copy link

changeset-bot bot commented Nov 14, 2023

⚠️ No Changeset found

Latest commit: 423fabe

Merging this PR will not cause a version bump for any packages. If these changes should not result in a new version, you're good to go. If these changes should result in a version bump, you need to add a changeset.

This PR includes no changesets

When changesets are added to this PR, you'll see the packages that this PR includes changesets for and the associated semver types

Click here to learn what changesets are, and how to add one.

Click here if you're a maintainer who wants to add a changeset to this PR

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants