tu2-atmanand / Task-Board

An Obsidian plugin to view and manage all your task in a much more efficient Kanban Board format. Easily manage your tasks throught your vault.
https://tu2-atmanand.github.io/task-board-docs/
GNU General Public License v3.0
5 stars 0 forks source link

feat : Adding Multiple tags to same task with custom colors #52

Closed tu2-atmanand closed 2 weeks ago

tu2-atmanand commented 1 month ago

At present I can only assign single tag to a task. Expand this feature to add multiple tags. For now keep the input field as text, later I can make it dropdown.

Then in the settingsTab, there will be a section Tag Colors. In this section, in each row, there will be tow columns, tag name and tag color. The Color has be to in RGBA format, so there is also transparency. The color will be added to the Font as well as to the border and with a small opacity it will also be the BG of this tag, design inpired from GitHub as shown below : Image

tu2-atmanand commented 1 month ago

Unfortunately, HTML's native <input type="color"> does not support transparency (alpha) adjustments directly—it only allows for selecting colors in the RGB format without alpha channels. Since this doesn't meet your requirement of specifying alpha transparency along with color selection, there are a few alternative approaches:

1. Use an Additional Input Field for Alpha

You can add an extra field that allows users to specify the alpha value, as you suggested. This is a simple and effective approach. You would capture the alpha value separately and then combine it with the selected hex color to form the RGBA value.

Here’s how to implement it:

const addTagColorButton = new Setting(contentEl).addButton((btn) =>
    btn.setButtonText("Add Tag Color").onClick(() => {
        const newTagSetting = new Setting(tagColorsContainer)
            .addText((text) =>
                text.setPlaceholder("Tag Name").onChange(async (newTag) => {
                    if (!this.globalSettings!.tagColors[newTag]) {
                        this.globalSettings!.tagColors[newTag] = ""; // Set empty color initially
                    }
                })
            )
            .addColorPicker((picker) =>
                picker.onChange(async (hexColor) => {
                    const tagName = newTagSetting.settingEl.querySelector("input")?.value;
                    if (tagName) {
                        this.globalSettings!.tagColors[tagName] = hexColor; // Save as hex initially
                        await this.saveSettings();
                    }
                })
            )
            .addText((alphaText) =>
                alphaText
                    .setPlaceholder("Alpha (0-1)")
                    .onChange(async (alpha) => {
                        const tagName = newTagSetting.settingEl.querySelector("input")?.value;
                        if (tagName) {
                            const hexColor = this.globalSettings!.tagColors[tagName];
                            const rgbaColor = hexToRgba(hexColor, parseFloat(alpha)); // Convert hex to RGBA with alpha
                            this.globalSettings!.tagColors[tagName] = rgbaColor;
                            await this.saveSettings();
                        }
                    })
            );
    })
);

2. Use a Library for Advanced Color Picker

To achieve both RGB and alpha selection with a single color picker, you can use a third-party library such as Pickr or jscolor. These libraries allow selecting RGBA values, including alpha, in a more comprehensive color picker interface.

Example Using Pickr:

<div id="color-picker"></div>
<script>
    const pickr = Pickr.create({
        el: '#color-picker',
        theme: 'nano', // or 'classic', 'monolith'
        default: '#42445a',
        swatches: ['#f44336', '#e91e63', '#9c27b0', '#673ab7'],
        components: {
            preview: true,
            opacity: true,  // Enable opacity (alpha channel)
            hue: true,
            interaction: {
                rgba: true,
                input: true,
            }
        }
    });

    pickr.on('change', (color) => {
        const rgbaColor = color.toRGBA().toString(); // rgba format
        // Save this rgbaColor to your settings
    });
</script>

This will allow the user to pick a color in RGBA format directly, including the alpha (opacity) value, without needing a separate input field.

Summary of Options:

  1. Extra input for Alpha (simple and native to HTML).
  2. Use a third-party library like Pickr or jscolor to offer full RGBA support within the color picker itself.

Let me know if you prefer one approach over the other or need more guidance on implementation!

tu2-atmanand commented 1 month ago

To integrate a full RGBA color picker into your TaskBoardSettingConstructUI.ts file using the Pickr library, you'll need to follow these steps:

Steps to Add Pickr:

  1. Include the Pickr Library: Add the Pickr library to your project. You can do this by downloading it or using a CDN. Include these links in your HTML or modify your Webpack/Parcel configuration to import the library.

    CDN Approach: Add the following lines to your HTML:

    <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@simonwep/pickr/dist/themes/nano.min.css" />
    <script src="https://cdn.jsdelivr.net/npm/@simonwep/pickr"></script>

    If you're using a module bundler like Webpack, you can install Pickr using npm:

    npm install @simonwep/pickr

    Then import it in your TypeScript file:

    import Pickr from '@simonwep/pickr';
  2. Create the Color Picker Element in the UI: Inside your constructUI function, add a placeholder <div> for the color picker component, which Pickr will bind to.

    Example:

    async constructUI(contentEl: HTMLElement, heading: string) {
       // ... existing code
    
       const colorPickerContainer = contentEl.createDiv({ cls: 'color-picker-container' });
    
       // Create "Add Tag Color" button
       const addTagColorButton = new Setting(contentEl).addButton((btn) =>
           btn.setButtonText("Add Tag Color").onClick(() => {
               const newTagSetting = new Setting(colorPickerContainer)
                   .addText((text) =>
                       text
                           .setPlaceholder("Tag Name")
                           .onChange(async (newTag) => {
                               if (!this.globalSettings!.tagColors[newTag]) {
                                   this.globalSettings!.tagColors[newTag] = ""; // Set empty color initially
                               }
                           })
                   );
    
               const colorPickerDiv = newTagSetting.settingEl.createDiv({
                   cls: "tag-color-picker",
                   attr: { id: "pickr-" + Date.now() }, // Unique ID for each instance
               });
    
               this.initializePickr(colorPickerDiv, newTagSetting);
           })
       );
    }
  3. Initialize Pickr: Now create a method in your file to initialize the Pickr color picker for each tag setting:

    initializePickr(element: HTMLElement, tagSetting: Setting) {
       const pickr = Pickr.create({
           el: element,
           theme: 'nano', // or 'classic', 'monolith'
           default: '#42445a',
           swatches: [
               '#f44336', '#e91e63', '#9c27b0', '#673ab7',
               '#3f51b5', '#2196f3', '#00bcd4', '#009688',
               '#4caf50', '#8bc34a', '#cddc39', '#ffeb3b',
               '#ffc107', '#ff9800', '#ff5722', '#795548'
           ],
           components: {
               preview: true,
               opacity: true,  // Enable alpha channel
               hue: true,
               interaction: {
                   hex: true,
                   rgba: true,
                   input: true,  // Input box for manual color entry
                   save: true,
               }
           }
       });
    
       // Handle color change event
       pickr.on('change', (color) => {
           const rgbaColor = color.toRGBA().toString(); // Convert to RGBA string
           const tagName = tagSetting.settingEl.querySelector("input")?.value;
           if (tagName) {
               this.globalSettings!.tagColors[tagName] = rgbaColor; // Save RGBA color
               this.saveSettings();  // Save settings after color change
           }
       });
    }
  4. Update globalSettings Interface: To store the tag colors, update your globalSettingsData interface by adding a tagColors property, which will store a key-value map of tag names and their respective RGBA colors.

    export interface globalSettingsData {
       tagColors: { [tagName: string]: string };  // Store tag-color pairs
       // ... other settings
    }

Final Touch:

This setup will now show an RGBA-compatible color picker using Pickr whenever a user wants to add a new tag and color. You’ll get full support for both RGB and alpha values in a single interface. The selected RGBA value will be saved in your plugin settings.

Let me know if you need further guidance with this!

tu2-atmanand commented 4 weeks ago

For now i have used the inbuilt Color picker itself and using a seprate field to take the value for alpha.

tu2-atmanand commented 4 weeks ago

This functionality has been implemented and working as expected.

I wan to do few test on this, hence moving this to Review column, after testing, close this issue.

tu2-atmanand commented 2 weeks ago

This feature has been working fine, tested.

Closing the issue.