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
Open
Show file tree
Hide file tree
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
2 changes: 2 additions & 0 deletions packages/vanilla-extract/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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:


### Debug identifiers

To improve the developer experience, `createTextStyle` accepts a debug identifier as the last argument.
Expand Down
66 changes: 46 additions & 20 deletions packages/vanilla-extract/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,34 +9,59 @@ import { precomputeValues } from '@capsizecss/core';
import { ComputedValues, CreateStyleObjectParameters } from './types';
import { capsizeStyle, capsizeVars } from './capsize.css';

interface MediaQueries {
'@media': Record<string, CreateStyleObjectParameters>;
interface ConditionalQueries {
'@media'?: Record<string, CreateStyleObjectParameters>;
'@container'?: Record<string, CreateStyleObjectParameters>;
}

const generateQueryVars = ({
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;

queries: Record<string, any>;
}) => {
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;
Comment on lines +24 to +35
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 😄)

};

const createVanillaStyle = ({
values,
mediaQueries,
conditionalQueries,
debugId,
}: {
values: ComputedValues;
mediaQueries?: MediaQueries;
conditionalQueries?: ConditionalQueries;
debugId?: string;
}) => {
const vars: StyleRule = {
vars: assignVars(capsizeVars, values),
};

if (typeof mediaQueries !== 'undefined') {
const mqs: StyleRule['@media'] = {};
Object.entries(mediaQueries['@media']).forEach(([mq, val]) => {
const builtValues =
'capHeightTrim' in val
? (val as ComputedValues)
: precomputeValues(val);
if (typeof conditionalQueries !== 'undefined') {
if (conditionalQueries['@media']) {
vars['@media'] = generateQueryVars({
queryType: '@media',
queries: conditionalQueries['@media'],
});
}

mqs[mq] = { vars: assignVars(capsizeVars, builtValues) };
});
vars['@media'] = mqs;
if (conditionalQueries['@container']) {
vars['@container'] = generateQueryVars({
queryType: '@container',
queries: conditionalQueries['@container'],
});
}
}

return composeStyles(capsizeStyle, style(vars, debugId));
Expand All @@ -48,26 +73,27 @@ function createTextStyle(
): string;
function createTextStyle(
args: CreateStyleObjectParameters,
mediaQueries?: MediaQueries,
conditionalQueries?: ConditionalQueries,
debugId?: string,
): string;
function createTextStyle(...args: any[]) {
const hasMediaQueries =
const hasConditionalQueries =
typeof args[1] !== 'undefined' && typeof args[1] !== 'string';
const debugId = hasMediaQueries ? args[2] : args[1];
const mediaQueries = hasMediaQueries ? args[1] : undefined;

const debugId = hasConditionalQueries ? args[2] : args[1];
const conditionalQueries = hasConditionalQueries ? args[1] : undefined;

if ('capHeightTrim' in args[0]) {
return createVanillaStyle({
values: args[0],
mediaQueries,
conditionalQueries,
debugId,
});
}

return createVanillaStyle({
values: precomputeValues(args[0]),
mediaQueries,
conditionalQueries,
debugId,
});
}
Expand Down
25 changes: 24 additions & 1 deletion packages/vanilla-extract/stories/Text.css.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,8 @@
import { style, createGlobalTheme } from '@vanilla-extract/css';
import {
style,
createGlobalTheme,
createContainer,
} from '@vanilla-extract/css';
import { createTextStyle, precomputeValues } from '../src';

const fontMetrics = {
Expand Down Expand Up @@ -58,6 +62,25 @@ export const responsiveText = createTextStyle(
'responsiveText',
);

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: 400px)`]: textValues.tablet,
[`${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',


export const responsiveThemedText = createTextStyle(
vars.typography.heading.mobile,
{
Expand Down
16 changes: 15 additions & 1 deletion packages/vanilla-extract/stories/Text.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ export const ThemedText = ({ text, background }: Props) =>
background ? ` style="background: ${background}"` : ''
}>${text}</div>`;

export const ResponsiveText = ({ text, background }: Props) =>
export const MediaResponsiveText = ({ text, background }: Props) =>
`<div class="${styles.fontFamily} ${styles.responsiveText}"${
background ? ` style="background: ${background}"` : ''
}>${text}</div>`;
Expand All @@ -24,3 +24,17 @@ export const ResponsiveThemedText = ({ text, background }: Props) =>
`<div class="${styles.fontFamily} ${styles.responsiveThemedText}"${
background ? ` style="background: ${background}"` : ''
}>${text}</div>`;

export const ContainerResponsiveText = ({ text, background }: Props) =>
[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.

<div class="${styles.fontFamily} ${styles.containerText}"${
background ? ` style="background: ${background}"` : ''
}>
${text}
</div>
</div>`,
)
.join('\n');
9 changes: 7 additions & 2 deletions packages/vanilla-extract/stories/vanilla-extract.stories.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
import {
BasicText,
ThemedText,
ResponsiveText,
MediaResponsiveText,
ResponsiveThemedText,
ContainerResponsiveText,
} from './Text';

export default {
Expand All @@ -24,8 +25,12 @@ export const Basic = container(BasicText({ text: 'Heading' }));

export const Themed = container(ThemedText({ text: 'Heading' }));

export const Responsive = container(ResponsiveText({ text: 'Heading' }));
export const Responsive = container(MediaResponsiveText({ text: 'Heading' }));

export const ResponsiveThemed = container(
ResponsiveThemedText({ text: 'Heading' }),
);

export const Container = container(
ContainerResponsiveText({ text: 'Heading' }),
);
Loading