Skip to content

Commit

Permalink
Readd css prop example & more doc
Browse files Browse the repository at this point in the history
  • Loading branch information
Luca Schneider committed Oct 9, 2024
1 parent d929ff7 commit e0ce2fd
Show file tree
Hide file tree
Showing 4 changed files with 53 additions and 13 deletions.
1 change: 0 additions & 1 deletion packages/docs/components/editor.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -290,7 +290,6 @@ export default function Editor() {
<div
style={{
margin: "16px 1ch",
overflow: "auto",
}}
dangerouslySetInnerHTML={{
__html: highlighter.codeToHtml(
Expand Down
8 changes: 7 additions & 1 deletion packages/example/app/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -127,7 +127,13 @@ export default function Home() {
<StyledLink href="https://github.com/jantimon/next-yak/tree/main/packages/example/app">
view code
</StyledLink>
<p>CSS Prop works if this is green</p>
<p
css={css`
color: green;
`}
>
CSS Prop works if this is green
</p>
<Inputs />
</main>
</YakThemeProvider>
Expand Down
11 changes: 3 additions & 8 deletions packages/yak-swc/yak_swc/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -583,19 +583,14 @@ where
}
}
props_or_spread.visit_mut_with(self);
fn visit_mut_jsx_attr(&mut self, n: &mut JSXAttr) {
if let JSXAttrName::Ident(ident) = &n.name {
if ident.sym == "css" {
let previous_inside_css_attribute = self.inside_css_attribute;
self.inside_css_attribute = true;
n.visit_mut_children_with(self);
self.inside_css_attribute = previous_inside_css_attribute;
}
}
}

// Visit JSX expressions for css prop support
fn visit_mut_jsx_opening_element(&mut self, n: &mut JSXOpeningElement) {
if !self.yak_library_imports.is_using_next_yak() {
return;
}
let css_prop = n.has_css_prop();
if let Some(css_prop) = css_prop {
let previous_inside_css_attribute = self.inside_element_with_css_attribute;
Expand Down
46 changes: 43 additions & 3 deletions packages/yak-swc/yak_swc/src/utils/css_prop.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,7 @@
use swc_core::{
common::{Span, DUMMY_SP},
ecma::ast::{
CallExpr, Callee, Expr, ExprOrSpread, Ident, JSXAttr, JSXAttrName, JSXAttrOrSpread,
JSXAttrValue, JSXExpr, JSXOpeningElement, KeyValueProp, ObjectLit, Prop, PropName,
PropOrSpread, SpreadElement,
CallExpr, Callee, Expr, ExprOrSpread, Ident, JSXAttr, JSXAttrName, JSXAttrOrSpread, JSXAttrValue, JSXElementName, JSXExpr, JSXOpeningElement, KeyValueProp, ObjectLit, Prop, PropName, PropOrSpread, SpreadElement
},
plugin::errors::HANDLER,
};
Expand All @@ -15,6 +13,31 @@ pub struct CSSProp {
}

impl CSSProp {
/// Transforms the css prop to a spread attribute, changes the call to invoke it without parameters
/// and inserts it into the correct position.
/// If the css prop has relevant props, they are removed and transformed into a merge call.
///
/// e.g.
/// ```jsx
/// <div css={css("divClassName")} />
/// ```
/// becomes
/// ```jsx
/// <div {...css("divClassName")({})} />
/// ```
/// and
/// ```jsx
/// <div css={css("divClassName")} style={{color: red}} className="myClassName" />
/// ```
/// becomes
/// ```jsx
/// <div {...__yak_mergeCssProp(
/// css("divClassName")({}),
/// {
/// style: {color: red},
/// className: "myClassName"
/// })} />
/// ```
pub fn transform(&self, opening_element: &mut JSXOpeningElement, merge_ident: &Ident) {
let result: Result<_, TransformError> = (|| {
let value = opening_element.attrs.remove(self.index);
Expand Down Expand Up @@ -148,7 +171,13 @@ pub trait HasCSSProp {
}

impl HasCSSProp for JSXOpeningElement {
/// Returns the index of the `css` attribute and the indices of other relevant attributes
/// (like `className` and `style`).
fn has_css_prop(&self) -> Option<CSSProp> {
if !is_native_element(&self.name) {
return None;
}

let mut css_index = None;
let mut relevant_props = Vec::new();

Expand All @@ -174,6 +203,17 @@ impl HasCSSProp for JSXOpeningElement {
}
}

// good enough for now. Better to use a list of known native elements.
fn is_native_element(name: &JSXElementName) -> bool {
match name {
JSXElementName::Ident(ident) => {
let first_char = ident.sym.chars().next().unwrap_or('\0');
first_char.is_ascii_lowercase()
}
_ => false,
}
}

#[derive(Debug)]
pub enum TransformError {
InvalidCSSAttribute(Span),
Expand Down

0 comments on commit e0ce2fd

Please sign in to comment.