maxmarcon / live_select

Dynamic (multi)selection field for LiveView
https://hex.pm/packages/live_select
Apache License 2.0
185 stars 35 forks source link

Tailwind classes are not extracted #22

Closed carlotm closed 1 year ago

carlotm commented 1 year ago

Hi all,

I have added deps/live_select/lib/live_select/component.*ex to the content array in my tailwind config file, but the classes are not extracted correctly (I don't find them in the compiled css).

If I change a line to something like active_option: ~W(text-white "bg-gray-600"), (note the quotes), tailwind extracts the class correctly.

This seems an upstream bug, but before I would like to make sure it's not only a problem of my setup.

Thank you

maxmarcon commented 1 year ago

I have added deps/live_select/lib/live_select/component.*ex to the content array in my tailwind config file,

it should be ../deps/live_select/lib/live_select/component.*ex, (or ../../../deps/live_select/lib/live_select/component.*ex for an umbrella app)

If I change a line to something like active_option: ~W(text-white "bg-gray-600"), (note the quotes), tailwind extracts the class correctly.

where do you change active_option? When rendering the live_select component or in the live_select's code? (your comment about upstream made me think that perhaps you've forked the repo, that's why I'm asking)

I doubt it's a bug, because classes work well for me on my local app that uses live_select.

If you could share some code and/or details about your setup, I'd be more than happy to take a look!

carlotm commented 1 year ago

it should be ../deps/live_select/lib/live_select/component.*ex, (or ../../../deps/live_select/lib/live_select/component.*ex for an umbrella app)

I am sorry (wrong paste), the path is correct.

where do you change active_option? When rendering the live_select component or in the live_select's code? (your comment about upstream made me think that perhaps you've forked the repo, that's why I'm asking)

In the live_select component code

This is my full tailwind config:

const colors = require("tailwindcss/colors");
const defaultTheme = require("tailwindcss/defaultTheme");

// Hex To RGB
const hexToRGB = (h) => {
  let r = 0,
    g = 0,
    b = 0;

  // 3 Digits
  if (h.length == 4) {
    r = "0x" + h[1] + h[1];
    g = "0x" + h[2] + h[2];
    b = "0x" + h[3] + h[3];

    // 6 6igits
  } else if (h.length == 7) {
    r = "0x" + h[1] + h[2];
    g = "0x" + h[3] + h[4];
    b = "0x" + h[5] + h[6];
  }

  return +r + " " + +g + " " + +b;
};

// With Opacity Value
const withOpacityValue = (variable) => {
  return ({ opacityValue }) => {
    if (opacityValue === undefined) {
      return `rgb(var(${variable}))`;
    }
    return `rgb(var(${variable}) / ${opacityValue})`;
  };
};

module.exports = {
  content: [
    "./js/**/*.js",
    "../lib/oha/**/*.*ex",
    "../lib/oha_web/**/*.*ex",
    "../storybook//**/*.*exs",
    "../deps/live_select/lib/live_select/component.*ex",
  ],
  darkMode: "class",
  theme: {
    outlineColor: ({ theme }) => ({
      DEFAULT: theme("colors.primary.DEFAULT"),
    }),
    outlineWidth: {
      DEFAULT: "2px",
    },

    container: {
      center: true,
      padding: "1rem",
    },
    fontFamily: {
      heading: ["var(--font-heading)", ...defaultTheme.fontFamily.sans],
      body: ["var(--font-body)", ...defaultTheme.fontFamily.sans],
    },
    skin: {
      white: hexToRGB(colors.white),
      secondary: {
        DEFAULT: hexToRGB(colors.gray[600]),
      },
      gray: {
        50: hexToRGB(colors.gray[50]),
        100: hexToRGB(colors.gray[100]),
        200: hexToRGB(colors.gray[200]),
        300: hexToRGB(colors.gray[300]),
        400: hexToRGB(colors.gray[400]),
        500: hexToRGB(colors.gray[500]),
        600: hexToRGB(colors.gray[600]),
        700: hexToRGB(colors.gray[700]),
        800: hexToRGB(colors.gray[800]),
        900: hexToRGB(colors.gray[900]),
      },
      sky: {
        DEFAULT: hexToRGB(colors.sky[600]),
        50: hexToRGB(colors.sky[50]),
        100: hexToRGB(colors.sky[100]),
        200: hexToRGB(colors.sky[200]),
        300: hexToRGB(colors.sky[300]),
        400: hexToRGB(colors.sky[400]),
        500: hexToRGB(colors.sky[500]),
        600: hexToRGB(colors.sky[600]),
        700: hexToRGB(colors.sky[700]),
        800: hexToRGB(colors.sky[800]),
        900: hexToRGB(colors.sky[900]),
      },
    },
    colors: {
      transparent: "transparent",
      current: "currentColor",
      black: colors.black,
      white: colors.white,
      gray: {
        50: withOpacityValue("--color-gray-50"),
        100: withOpacityValue("--color-gray-100"),
        200: withOpacityValue("--color-gray-200"),
        300: withOpacityValue("--color-gray-300"),
        400: withOpacityValue("--color-gray-400"),
        500: withOpacityValue("--color-gray-500"),
        600: withOpacityValue("--color-gray-600"),
        700: withOpacityValue("--color-gray-700"),
        800: withOpacityValue("--color-gray-800"),
        900: withOpacityValue("--color-gray-900"),
      },
      primary: {
        DEFAULT: withOpacityValue("--color-primary"),
        50: withOpacityValue("--color-primary-50"),
        100: withOpacityValue("--color-primary-100"),
        200: withOpacityValue("--color-primary-200"),
        300: withOpacityValue("--color-primary-300"),
        400: withOpacityValue("--color-primary-400"),
        500: withOpacityValue("--color-primary-500"),
        600: withOpacityValue("--color-primary-600"),
        700: withOpacityValue("--color-primary-700"),
        800: withOpacityValue("--color-primary-800"),
        900: withOpacityValue("--color-primary-900"),
      },
      secondary: withOpacityValue("--color-secondary"),
    },
    extend: {
      transitionDuration: {
        DEFAULT: "300ms",
      },
      fontSize: {
        "4xl": "2rem",
        "line-height": "3rem",
      },
      borderRadius: {
        xl: "10px",
      },
      boxShadow: {
        DEFAULT: "1px 1px 5px 0 rgba(0, 0, 0, 0.16)",
      },
      colors: {
        success: "#28a745",
        danger: "#dc3545",
        error: "#dc3545",
        warning: "#ffc107",
        info: "#17a2b8",
        social: {
          facebook: "#3b5998",
          twitter: "#1da1f2",
          pinterest: "#bd081c",
          whatsapp: "#25d366",
        },
      },
      animation: {
        "spin-slow": "spin 3s linear infinite",
      },
      backgroundColor: {
        background: withOpacityValue("--color-background"),
        foreground: withOpacityValue("--color-foreground"),
        input: withOpacityValue("--color-input"),
      },
      borderColor: {
        divider: withOpacityValue("--color-divider"),
        border: withOpacityValue("--color-border"),
      },
      textColor: {
        normal: withOpacityValue("--color-text-normal"),
        muted: withOpacityValue("--color-text-muted"),
        highlighted: withOpacityValue("--color-text-highlighted"),
        placeholder: withOpacityValue("--color-text-placeholder"),
        component: withOpacityValue("--color-text-component"),
      },
    },
  },
  plugins: [
    require("@tailwindcss/typography"),
    require("@tailwindcss/aspect-ratio"),
  ],
  safelist: [
    { pattern: /w-[\d+]/ },
    { pattern: /gap-[\d+]/ },
    { pattern: /grid-cols-[\d+]/ },
    { pattern: /col-span-[\d+]/ },
    "text-success",
    "Card",
  ],
};

And my config section regarding tailwind (and dart sass):

config :tailwind,
  version: "3.1.0",
  oha: [
    # css.i (to be ignored by live_reload)
    args: ~w(
      --config=oha.tailwind.config.js
      --input=../priv/static/tmp/oha.tailwind.css.i
      --output=../priv/static/oha.css
    ),
    cd: Path.expand("../assets", __DIR__)
  ],
  storybook: [
    args: ~w(
      --config=tailwind.config.js
      --input=css/storybook.css
      --output=../priv/static/assets/storybook.css
    ),
    cd: Path.expand("../assets", __DIR__)
  ]

config :dart_sass,
  version: "1.49.11",
  oha: [
    args: ~w(css/oha.scss ../priv/static/tmp/oha.tailwind.css.i),
    cd: Path.expand("../assets", __DIR__)
  ]

Is there any other relevant file?

Thank you

maxmarcon commented 1 year ago

In the live_select component code

how are you importing live select? As a hex dependency, as a path dependency, or other?

maxmarcon commented 1 year ago

The more code you share the better. Showing how you're rendering live_select would help.

You said you can't find the classes in the css... But do you see the live select component styled correctly on your app?

Meaning like here: https://live-select.fly.dev/

carlotm commented 1 year ago

I am using live_select as a dependency.

It's almost like the demo, but I noticed this issue in the styling:

Screenshot_2023-03-21_15-32-15

The second item is the select one (using the keyboard) and the items looks too compact compared to the demo (I could be wrong).

And the tags are missing some style, compared to the demo:

Screenshot_2023-03-21_15-37-34

This is how I render live_select

def render(assigns) do
  ~H"""
  <OHA.Components.Flash.flashes flash={@flash} />
  <.form :let={f} for={@changeset} phx-change="change" phx-submit="save">
    <OHA.Components.Form.form_field form={f} field={:favorite_driver}>
      <LiveSelect.live_select
        id="live-select-driver"
        form={f}
        field={:favorite_driver}
        mode={:single}
        update_min_len={1}
        options={F1.drivers_as_options()}
        allow_clear={true}
      />
    </OHA.Components.Form.form_field>

    <OHA.Components.Form.form_field form={f} field={:worst_drivers}>
      <LiveSelect.live_select
        id="live-select-worst_drivers"
        form={f}
        field={:worst_drivers}
        mode={:tags}
        update_min_len={1}
        options={F1.drivers_as_options()}
        allow_clear={true}
      />
    </OHA.Components.Form.form_field>

    <button type="submit" class="Btn Btn-primary mt-2">Save</button>
  </.form>
  """
end
maxmarcon commented 1 year ago

Thanks for sharing this.

Interesting, so you're using it with live storybook. Nice.

Could it be that you're using a different tailwind config file when running storybook? Looking at your config file above:

config :tailwind,
  version: "3.1.0",
  oha: [
    # css.i (to be ignored by live_reload)
    args: ~w(
      --config=oha.tailwind.config.js
      --input=../priv/static/tmp/oha.tailwind.css.i
      --output=../priv/static/oha.css
    ),
    cd: Path.expand("../assets", __DIR__)
  ],
  storybook: [
    args: ~w(
      --config=tailwind.config.js
      --input=css/storybook.css
      --output=../priv/static/assets/storybook.css
    ),
    cd: Path.expand("../assets", __DIR__)
  ]

I see a oha.tailwind.config.js (I presume for your app) and a tailwind.config.js for storybook.

Did you add the live_select path to the content array in both files?

carlotm commented 1 year ago

I am sure I am loading the ../priv/static/oha.css which should contain the live_select classes.

Interestingly though, it seems that only the color related classes are missing (thus the transparent tags)

It may be that some part of my tailwind configuration (the theme and skin parts look suspicious) clashes with those color classes.

Unfortunately I am not an expert of Tailwind :(

I would say that this is not an issue with Live Select, so I am ok to close this issue.

maxmarcon commented 1 year ago

I tested parts of your tailwind config locally and I believe there are 3 issues:

  1. By having theme -> color you are completely overriding the default tailwind color classes. So live_select can't find for example bg-blue-400, since you don't define any blue color.

  2. If you want to extend the default tailwind classes, you have to use theme -> extend -> color. But using both as you're doing doesn't make sense. You either replace the defaults, or you extend them

  3. If I put your theme -> color config under theme -> extend -> color the tag colors look good, (not overriding the default bg-blue color classes), but the background of the dropdown doesn't look good. This is because I believe those withOpacityValue("--color-primary-100") values are broken, and the bg-gray color is not available. withOpacityValue returns a function not a color.

I hope this helps.

carlotm commented 1 year ago

Yeah, I was suspecting the same. I will happily forward your feedback to the frontend developer :)

Thanks a lot