themesberg / flowbite-svelte

Official Svelte components built for Flowbite and Tailwind CSS
https://flowbite-svelte.com
MIT License
2.13k stars 262 forks source link

Overwrite+adding default classes to theme #833

Closed Dudek-AMS closed 1 year ago

Dudek-AMS commented 1 year ago

Im using the Button Component with a custom primary color and a 'href' attribute

  <Button href="/Admin/ResponseTemplates"
        ><span><i class="fas fa-fw fa-x" /> Abbrechen</span>
      </Button>

inside my global.css i set colors for links

a {
  @apply text-primary-700;
}
a:hover {
  @apply text-primary-600;
}

the link inside the button will be text-primary-600 on hover while the button is bg-primary-800 and i have to explicitely use hover:text-white on the Button element to prevent it being unreadable.

Solution: checking the code of the component

const colorClasses = {
    alternative: 'text-gray-900 bg-white border border-gray-200 hover:bg-gray-100 dark:bg-gray-800 dark:text-gray-400 hover:text-primary-700 focus:text-primary-700 dark:focus:text-white dark:hover:text-white',
    blue: 'text-white bg-blue-700 hover:bg-blue-800 dark:bg-blue-600 dark:hover:bg-blue-700',
    dark: 'text-white bg-gray-800 hover:bg-gray-900 dark:bg-gray-800 dark:hover:bg-gray-700',
    green: 'text-white bg-green-700 hover:bg-green-800 dark:bg-green-600 dark:hover:bg-green-700',
    light: 'text-gray-900 bg-white border border-gray-300 hover:bg-gray-100 dark:bg-gray-800 dark:text-white dark:border-gray-600 dark:hover:bg-gray-700 dark:hover:border-gray-600',
    primary: 'text-white bg-primary-700 hover:bg-primary-800 dark:bg-primary-600 dark:hover:bg-primary-700',
    purple: 'text-white bg-purple-700 hover:bg-purple-800 dark:bg-purple-600 dark:hover:bg-purple-700',
    red: 'text-white bg-red-700 hover:bg-red-800 dark:bg-red-600 dark:hover:bg-red-700',
    yellow: 'text-white bg-yellow-400 hover:bg-yellow-500 ',
    none: ''
};

instead of hardcoding it i suggest using a global store or some other method, to allow modyfing it during runtime like

$buttonThemesStore.colorClasses.primary += ' hover:text-white';

doing this way would also allow to add new colors to the components

shinokada commented 1 year ago

Thank you for your contribution. Currently, we don't have a plan to move styles globally. But you can set color props to none and add your classes using class="your-class".

Dudek-AMS commented 1 year ago

While this work, it will force me to do this every time i use the component adding redudant code and bad dx... ofc i could make a wrapper and then use the flowbite component inside with the correct classes - but still think its bad design

shinokada commented 1 year ago

Can you add your class to the tailwind.config.cjs and use it in your components? Or you can try one of Headless UIs?

Dudek-AMS commented 1 year ago

Its the component from flowbite-svelte itsself which makes it impossible to use 'custom' themes.... i can set color to none and then define all the classes I want to have - works but i will to do this every time im going to use the component

But I can't define presets for the components <Button color="primary">abc</Button>

is a preset you defined in the components...... but I wont be able to use

<Button color="myCustomColor"></Button>

Thats why i suggest to outsource the color presets out of the component and make them accessible via config file or better via a global export/svelte story

shinokada commented 1 year ago

By doing that I assume there will be many items in the config file and styling will be done in the the file rather than your svelte file. I'm now sure if other uses want to do in that way.

Dudek-AMS commented 1 year ago

Well you will only need the config files if you have the need for it. Otherwise use default values

Going svelte store way people can easily split the code and add the things they want to do in runtime If making config files its still possible to import differenct config files and use a (deep)merge. So you can still split code like you want.

shinokada commented 1 year ago

Do you want to show some examples forking this stackblitz?

Dudek-AMS commented 1 year ago

https://stackblitz.com/edit/sveltejs-kit-template-default-fnwquw?file=src%2Froutes%2F%2Blayout.svelte

"$lib/flowbite.theme.js"; and "$lib/NewButton.svelte" shall not be part of the userland code, but from the flowbite-svelte library

modified theme in +layout.svelte, but could be done anywhere else - even outside of svelte.

jjagielka commented 1 year ago

This is in line with my approach presented in #711. I'll spend some time on it during the weekend to move it forward.

shinokada commented 1 year ago

I can see the benefit of doing this way but there are disadvantage:

<script>
  import { ButtonGroup, Button, Label } from 'flowbite-svelte';
  import NewButton from "$lib/NewButton.svelte";
  import { theme } from '$lib/flowbite.theme.js';

  if (!$theme.buttons.colorClasses.light.includes('text-red-900')) {
    $theme.buttons.colorClasses.light = '!text-red-900 ' + $theme.buttons.colorClasses.light;
  }
</script>

<div class='p-16'>
  <div class="py-4">Pills</div>
  <ButtonGroup class="space-x-px">
    <Button color="light" class="!text-red-900">Profile</Button>
    <Button color="light" class="!text-green-900">Settings</Button>
    <Button color="light" class="!text-purple-500">Messages</Button>
  </ButtonGroup>
    <div class="py-4">Pills NewButton but extended</div>
  <ButtonGroup class="space-x-px">
    <NewButton color="light">Profile</NewButton>
    <NewButton color="light">Settings</NewButton>
    <NewButton color="light">Messages</NewButton>
  </ButtonGroup>
</div>

Benefit: Users can change their style by overwriting Svelte store values.

Disadvantage: Not flexible as you see in the above example when you want to change the color by button. You have to use unnecessary if-statements if you want to change different values.

r25s commented 1 year ago

I'm also pulling out my hair trying to overcome hardcoded classes. Especially on the Input element where it seems that you cannot override the classes at all, you can just append or prepend additional classes, leading to a lot of duplication of classes on the element ...unless I'm missing something.

shinokada commented 1 year ago

@ron-wade There is a PR for your issue that we may merge. But not at the moment.

Dudek-AMS commented 1 year ago

Well you would change the theme store somewhere else, not where you gonna use the components - like a global layout file or even complety outside of svelte - but i see your point and i think there's a solution...

the simple appending is a really bad example - i see two solutions for it

1) use a custom store, checking the classes and filter out duplicates before updating the store 2) use a helper function in userland

import { theme, deduplicateCSSClasses } from '$lib/flowbite.theme.js';
$theme.buttons.colorClasses.light = deduplicateCSSClasses($theme.buttons.colorClasses.light + ' text-red-900');
function deduplicateCSSClasses(input: string) : string {
    let splitted = input.split(/\s+/);
    let uniqued = [...new Set(splitted)];
    return uniqued.join(' ');
}

Not flexible as you see in the above example when you want to change the color by button.

If you need to change the color per button (one time usage) - the suggested change isnt what its for... its just if you want to re-use it on multiple times, probably all over your project.

shinokada commented 1 year ago

v0.38.1 uses Tailwind Merge so that you can overwrite styles by adding them to the class. Please try it out and let us know what you think.

<script>
    import { Button } from 'flowbite-svelte'
</script>

<Button href="/about" class="!bg-blue-500">
     Button 1
</Button>

<Button href="/about" class="!bg-green-500">
     Button 2
</Button>
JoshJarabek7 commented 1 year ago

I too am unable to get this to work. I'm using the exclamation point before the classes, nothing is working.

It keeps choosing the default class no matter on the NavUl. For some reason, the tailwind merge isn't working for it. The padding color is always bg-gray-800.

Dudek-AMS commented 1 year ago

v0.38.1 uses Tailwind Merge so that you can overwrite styles by adding them to the class. Please try it out and let us know what you think.

<script>
  import { Button } from 'flowbite-svelte'
</script>

<Button href="/about" class="!bg-blue-500">
   Button 1
</Button>

<Button href="/about" class="!bg-green-500">
   Button 2
</Button>

thats not the same like suggested example.. i will need to reduplicate all the code everytime im gonna use it.

shinokada commented 1 year ago

@Dudek-AMS You can take this approach.

  1. Create your button component in the lib dir:
// src/lib/MyButton.svelte
<script>
  import { Button } from 'flowbite-svelte'
</script>

<Button color="green" pill class="p-8">

<slot />

</Button>
  1. Use it in your project
<script>
  import MyButton from "$lib/MyButton.svelte"
</script>

<MyButton>My New Button</MyButton>

image

https://sveltejskittemplatedefaultefqg-kxp3--5173--77657b1e.local-corp.webcontainer.io/customization

shinokada commented 1 year ago

I close the issue for now. Thank you for your contribution. Please feel free to open a new issue.