I'm building an ecommerce platform using GatsbyJS and Snipcart. It works well, but I want to override the default theme provided by Snipcart, and when I want to change the main default CSS through gatsby-config.js for some reason, it does not work.
Anyone has a solution? Thanks.
This code below makes the snipcart to stop functioning, exactly when I add the styles option:
{
resolve: 'gatsby-plugin-snipcartv3',
options: {
apiKey: 'API_IS_HIDDEN_FOR_A_REASON',
autopop: true,
styles: '.src/components/layout.css'
}
},
The question is how to make Snipcart version 3 to accept different styles provided by me when used with GatsbyJS? I tried their documentation, but there was not much, also looked on github as well.
I found the easiest way to do this was as follows:
In the snipcart plugin config options, set styles to false so it doesn't link the default stylesheet
{
resolve: 'gatsby-plugin-snipcartv3',
options: {
apiKey: process.env.SNIPCART_KEY,
autopop: false,
styles: false
}
}
Create a new stylesheet (e.g., src/styles/cart.css)
Copy the styles from Snipcart's default stylesheet into your cart.css, and make your desired customizations
Import your cart.css into your Layout component (or into gatsby-browser.js)
Related
Is there any way to configure gatsby to inject a style file using a link tag?
currently, I have a global style (style.less) which I import it using a Layout Component. It's ok but It injects all CSS content into each page and bumps the page size.
I want to configure gatsby to load this style file using a link tag instead of injecting directly into DOM. webpack has an option for this purpose but I couldn't find anything similar for Gatsby.
Try:
exports.onCreateWebpackConfig = ({ actions, loaders, getConfig }) => {
const config = getConfig();
config.module.rules = [
...config.module.rules.filter(rule => String(rule.test) !== String(/\.jsx?$/)),
{
test: /\.link\.css$/i,
use: [
{ loader: `style-loader`, options: { injectType: `linkTag` } },
{ loader: `file-loader` },
],
},
];
actions.replaceWebpackConfig(config);
};
Gatsby allows you to customize the webpack's configuration by exposing some APIs (such as onCreateWebpackConfig or setWebpackConfig) functions.
The code is quite self-explanatory if you take into account the style-loader from webpack. Basically, you are setting some custom loaders for all files that match the regular expression, and finally, you override the default configuration with actions.replaceWebpackConfig(config).
For further details check Adding Custom webpack configuration docs.
In addition, regarding your original issue, you don't need to add your global styles in your Layout component since it will cause what you said, it will bump the page size. With Gatsby, you can use gatsby-browser.js API to add global styles like (in your gatsby-browser.js file):
import './src/your/path/to/global/style.less';
Check the link you've provided (Standard Styling with Global CSS file).
I am using Vue with Tailwind right now.
Here is my current Tailwind config:
const defaultTheme = require('tailwindcss/defaultTheme');
module.exports = {
purge: [],
theme: {
extend: {
fontFamily: {
sans: ['Inter var', ...defaultTheme.fontFamily.sans],
},
},
},
variants: {},
plugins: [],
}
I am using the Inter var font, because on OSX systems the default font weights do not work. Right now, I want to build this project, but in the production version it does not apply the correct font family. I've tried to import the font family via a html link and css import, but neither of those worked.
If you're on Vue-CLI, I'd recommend adding the typeface via NPM for maintainability, and import it into your entry file (e.g. main.js). This package will take care of referencing and importing the webfont(s) for you, so there's no need to create additional CSS anymore.
Installing the font
npm i typeface-inter
Importing it
import Vue from 'vue';
import 'typeface-inter';
// ...
And of course, you'll still need to extend the font-family (or simply adding it to the list will work too).
I'm trying to create a custom component for my markdown that accepts an image source. I am unable to display the image via the custom component because the image is not found because it doesn't exist
I also realised the image path is generated by GatsbyJS and I have no idea how to retrieve the path of the image in markdown.
I do have a custom component that holds some text but I couldn't do the same thing for images.
Here is a simple markdown with a title and a few words.
index.md
---
title: ToDoApp
---
Hi this is my todoapp app. Below is a bunch of screens
<imageholder src='./screen1.png'></imageholder>
![Image from Gyazo](./screen1.png) <!-- it displays... -->
I've created a custom component named imageholder where it holds some logic (in a near future...) in displaying the image
ImageHolder.js
import React from "react"
export default class ImageHolder extends React.Component {
render() {
return (
<img src={this.props.src} alt="Logo"/>
)
}
}
project-post.js
const renderAst = new rehypeReact({
createElement: React.createElement,
components: {
"imageholder": ImageHolder
},
}).Compiler
And I received this...
This is really tricky since (AFAIK) you can't pass props from page component to custom component with rehype-react. I think you'd need to do something similar to gatsby-remark-images, which locates the images' paths and set them.
I wrote this plugin that mimics gatsby-remark-images, but for custom components like in your case.
Here's the default setting, you can override the component name and pass in additional image transformation options.
// gatsby-config.js
module.exports = {
plugins: [
{
resolve: `gatsby-transformer-remark`,
options: {
plugins: [
{
resolve: `gatsby-remark-custom-image-component`,
options: {
// plugin options
componentName: 'image-wrapper',
imagePropName: 'src',
sharpMethod: 'fluid',
// fluid's arguments, see gatsby-plugin-sharp docs
quality: 50,
maxWidth: 800,
}
},
],
},
},
Then use it in your markdown:
<image-wrapper src='./hero.jpg'></image-wrapper>
And get the image props in your custom component.
//src/components/ImageWrapper.js
import React from 'react'
// the result of sharp's image transformation will be passed directly to this component.
// so if you use `fluid` as `sharpMethod`, you'll get
// src, srcSet, base64, aspectRatio, srcSetType, sizes, density, originalImage.
// Please refer to `gatsby-plugin-sharp` docs.
const ImageWrapper = ({ src, srcSet }) => <img src={src} srcSet={srcSet} />
export { ImageWrapper }
The issue is that props are passed as strings to rehype - the component doesn't receive the asset hashed value when the markdown is processed and built by Gatsby. So, the prop isn't the same as the image tag's src once you build the site, and it's not finding the asset hashed file.
This plugin, Gatsby Remark Copy Linked Files, moves your referenced asset files to a public folder, and passes the correctly hashed asset path, but by default only for img, a, audio, and video tags (not for custom components).
To solve for this, move the plugin from node_modules into a /plugin folder in the project root, and add the desired custom components and props at this line. In your case, it looks like it would be:
// Handle a tags.
extractUrlAttributeAndElement($(`a[href]`), `href`).forEach(processUrl)
// Manually added custom tags
extractUrlAttributeAndElement($(`imageholder[src]`), `src`).forEach(processUrl)
Obviously this would be better served as an option for the plugin in a configuration block in gatsby-config, but this worked for me in a pinch.
Maybe it's just me but I´m pretty much annoyed of defining my GraphQL Queries/Mutations with backticks. The problem here is that, if I have to apply some changes to the query string, it's pretty annoying to reformat the string inside the backticks.
Is there a clever way to define a more readable and maintainable GraphQL Query/Mutation with JavaScript? It's also hard to find missing brackets when the query string is messed up.
I am doing like this right now:
import gql from 'graphql-tag';
export const fancyMutation = gql`
mutation($id: ID!)
{
delete_something(id:$id) {
id
foo
bar
}
}
`;
You can also put your queries into their own files, e.g. with a .graphql or .gql file extension, and use the graphql-tag/loader to load the query from the file where you need it.
Given this query in its own file:
query CurrentUserForLayout {
currentUser {
login
avatar_url
}
}
With webpack you would need the following configuration:
module: {
rules: [
{
test: /\.(graphql|gql)$/,
exclude: /node_modules/,
loader: 'graphql-tag/loader',
},
],
},
Then you could load it like that:
import React, { Component } from 'react';
import { graphql } from 'react-apollo';
import currentUserQuery from './currentUser.graphql';
class Profile extends Component { ... }
Profile.propTypes = { ... };
export default graphql(currentUserQuery)(Profile)
Update:
You can also have multiple queries in one file:
query MyQuery1 {
...
}
query MyQuery2 {
...
}
You can then load them like this:
import { MyQuery1, MyQuery2 } from 'query.gql'
Other than that I don't know about other options to define queries inline. The backticks aren't graphql specific. It just uses the es6 template tags like e.g. styled components does to define inline css. Your only option is to get an IDE that can recognize graphql queries to provide editing help and code highlighting. IntelliJ Editors (IDEA, WebStorm, PyCharm) have a plugin for that like #Victor Vlasenko pointed out.
JS GraphQL WebStorm plugin starting from version 1.4.1 supports embedded GraphQL strings.
From the WebStorm menu select File -> Settings -> Plugins -> Browse repositories and find JS GraphQL plugin. Check that you have at least version 1.4.1 of this plugin installed.
When installed it should highlight braces and let you reformat GraphQL inside string by selecting code block and choosing Code -> Reformat code from IDE menu.
This plugin project page is located here:
https://github.com/jimkyndemeyer/js-graphql-intellij-plugin
I'd like to declare my styles (stylus) inside of my React component classes as such. Preferably while also utilizing CSS modules:
export default class HelloWorld extends Component {
render() {
return (
<div className={styles.hello} />
);
}
static styles = `
.hello
display block
`;
}
or even perhaps
const styles = stylus`
.hello
display block
`;
const HelloWorld = () => <div className={styles.hello} />
The goal here is to compile the styles into a stylesheet via stylus (or another preprocessor), strip the style block from the resulting javascript bundle, and access styles through CSS modules and the className property in JSX. I'd prefer to have these compiled at compile time (babel/webpack) rather than at runtime.
I'm not necessarily looking for hard and fast code, but any direction would be greatly appreciated. I'm not sure if all of this is even possible, although some of it definitely should be. I understand that accessing styles via styles. may not be feasible.
I've never written a babel or webpack plugin so I barely know where to start. Most of the documentation and tutorials that I read didn't seem to get me where I wanted to go.
Thanks
What you're trying to do is not possible, but there is a workaround; unfortunately, the answer might taste like bathtub gin. As you are probably aware, you cannot directly require Stylus. Accordingly, your forced to use a Stylus loader which you have two options, stylus-loader or Walmarts stylus-relative-loader, I would recommend the latter. Here is where things get a bit convoluted. Since you want to use CSS modules and compile the styles into a stylesheet, you will have to use the extract-text-webpack-plugin.
Long story short, if you are using Webpack 1.x here's an example configuration of the loader which you will need to implement into your Webpack config, which uses extract-text-webpack-plugin, css-modules, and stylus-relative-loader.
module: {
loaders: [{
test: /\.styl$/,
loader: ExtractTextPlugin.extract('style-loader', 'css?modules&importLoaders=1&localIdentName=[name]__[local]___[hash:base64:5]!stylus-relative-loader')
}]
},
plugins: [
new ExtractTextPlugin('main.css')
]
From here all you need to do is move your Stylus to a separate file like my-styles.styl and then require it into your React component like so.
const styles = require('./my-styles.styl')
const HelloWorld = () => <div className={styles.hello} />
PS. Sorry, if this is not what you're looking for but my "reputation" does not allow me to ask questions via comments nor can I use more than two links.