diff --git a/code/datums/components/palette.dm b/code/datums/components/palette.dm index 2ae66f50b23..0fb937a3b11 100644 --- a/code/datums/components/palette.dm +++ b/code/datums/components/palette.dm @@ -106,7 +106,7 @@ var/is_right_clicking = LAZYACCESS(params2list(params), RIGHT_CLICK) var/index = text2num(choice) if(is_right_clicking) - var/chosen_color = input(user, "Pick new color", "[parent]", colors[index]) as color|null + var/chosen_color = tgui_color_picker(user, "Pick new color", "[parent]", colors[index]) if(chosen_color && !QDELETED(src) && !IS_DEAD_OR_INCAP(user) && user.is_holding(parent)) colors[index] = chosen_color update_radial_list() diff --git a/code/game/machinery/telecomms/machine_interactions.dm b/code/game/machinery/telecomms/machine_interactions.dm index 7a606d42641..9b733931db2 100644 --- a/code/game/machinery/telecomms/machine_interactions.dm +++ b/code/game/machinery/telecomms/machine_interactions.dm @@ -322,7 +322,7 @@ info["name"] = new_name // No color changing for channels with theme settings if(!GLOB.freqtospan["[freq]"]) - var/new_color = input(usr, "Choose color for frequency", "Modifying Frequency Information", info["color"]) as color|null + var/new_color = tgui_color_picker(usr, "Choose color for frequency", "Modifying Frequency Information", info["color"]) if(new_color) info["color"] = new_color frequency_infos[params["freq"]] = info @@ -341,7 +341,7 @@ for(var/list/channel in get_channels()) if(channel["freq"] == freq || channel["name"] == name) return - var/color = input(usr, "Choose color for frequency", "Adding Frequency Information") as color|null + var/color = tgui_color_picker(usr, "Choose color for frequency", "Adding Frequency Information") if(!color) return frequency_infos[num2text(freq)] = list( diff --git a/code/game/objects/items.dm b/code/game/objects/items.dm index 31d158374f1..5f485bfd983 100644 --- a/code/game/objects/items.dm +++ b/code/game/objects/items.dm @@ -1753,7 +1753,7 @@ /// Common proc used by painting tools like spraycans and palettes that can access the entire 24 bits color space. /obj/item/proc/pick_painting_tool_color(mob/user, default_color) - var/chosen_color = input(user,"Pick new color", "[src]", default_color) as color|null + var/chosen_color = tgui_color_picker(user, "Pick new color", "[src]", default_color) if(!chosen_color || QDELETED(src) || IS_DEAD_OR_INCAP(user) || !user.is_holding(src)) return set_painting_tool_color(chosen_color) diff --git a/code/game/objects/items/dyespray.dm b/code/game/objects/items/dyespray.dm index 1ba28812945..a62a17f4352 100644 --- a/code/game/objects/items/dyespray.dm +++ b/code/game/objects/items/dyespray.dm @@ -57,8 +57,7 @@ if(!user.can_perform_action(src, NEED_DEXTERITY)) return - var/new_grad_color = input(user, "Choose a secondary hair color:", "Character Preference", human_target.get_hair_gradient_color()) as color|null - + var/new_grad_color = tgui_color_picker(user, "Choose a secondary hair color:", "Character Preference", human_target.get_hair_gradient_color()) if(!new_grad_color || !user.can_perform_action(src, NEED_DEXTERITY) || !target.IsReachableBy(user)) return @@ -106,7 +105,7 @@ return var/default_color = overlay.dye_color || overlay.draw_color - var/new_color = input(user, "Choose a color for [selected]:", "Character Preference", default_color) as color|null + var/new_color = tgui_color_picker(user, "Choose a color for [selected]:", "Character Preference", default_color) if(isnull(new_color) || new_color == default_color || !user.can_perform_action(src, NEED_DEXTERITY)) return if(QDELETED(selected) || !(selected in target.organs)) diff --git a/code/game/objects/items/frog_statue.dm b/code/game/objects/items/frog_statue.dm index 62c13389d1e..8c95ef4951b 100644 --- a/code/game/objects/items/frog_statue.dm +++ b/code/game/objects/items/frog_statue.dm @@ -146,7 +146,7 @@ new_frog.name = frog_name /obj/item/frog_contract/proc/select_frog_color(mob/user, mob/living/basic/leaper/new_frog) - var/frog_color = input(user, "Select your frog's color!" , "Pet toad color", COLOR_GREEN) as color|null + var/frog_color = tgui_color_picker(user, "Select your frog's color!" , "Pet toad color", COLOR_GREEN) if(isnull(frog_color)) to_chat(user, span_warning("Please choose a valid color.")) select_frog_color(user, new_frog) diff --git a/code/game/objects/items/rcd/RLD.dm b/code/game/objects/items/rcd/RLD.dm index 7d91451eb2c..0a038ebc650 100644 --- a/code/game/objects/items/rcd/RLD.dm +++ b/code/game/objects/items/rcd/RLD.dm @@ -69,7 +69,7 @@ mode = GLOW_MODE to_chat(user, span_notice("You change RLD's mode to 'Light Launcher'.")) if("Color Pick") - var/new_choice = input(user,"","Choose Color",color_choice) as color + var/new_choice = tgui_color_picker(user, "", "Choose Color", color_choice) if(new_choice == null) return diff --git a/code/game/objects/items/stacks/wrap.dm b/code/game/objects/items/stacks/wrap.dm index 600c7b3e451..22faa7d0502 100644 --- a/code/game/objects/items/stacks/wrap.dm +++ b/code/game/objects/items/stacks/wrap.dm @@ -53,8 +53,8 @@ set_greyscale(colors = list(generated_base_color, generated_ribbon_color)) /obj/item/stack/wrapping_paper/click_alt(mob/user) - var/new_base = input(user, "", "Select a base color", color) as color - var/new_ribbon = input(user, "", "Select a ribbon color", color) as color + var/new_base = tgui_color_picker(user, "", "Select a base color", color) + var/new_ribbon = tgui_color_picker(user, "", "Select a ribbon color", color) if(!new_base || !new_ribbon) return CLICK_ACTION_BLOCKING diff --git a/code/game/objects/structures/curtains.dm b/code/game/objects/structures/curtains.dm index 7cb8e8c68d3..ec864ca5a86 100644 --- a/code/game/objects/structures/curtains.dm +++ b/code/game/objects/structures/curtains.dm @@ -44,7 +44,7 @@ /obj/structure/curtain/attackby(obj/item/W, mob/user) if (istype(W, /obj/item/toy/crayon)) - color = input(user,"","Choose Color",color) as color + color = tgui_color_picker(user, "", "Choose Color", color) else return ..() diff --git a/code/game/objects/structures/dresser.dm b/code/game/objects/structures/dresser.dm index c43730070a1..f3e56bad87e 100644 --- a/code/game/objects/structures/dresser.dm +++ b/code/game/objects/structures/dresser.dm @@ -45,7 +45,7 @@ if(new_undies) dressing_human.underwear = new_undies if("Underwear Color") - var/new_underwear_color = input(dressing_human, "Choose your underwear color", "Underwear Color", dressing_human.underwear_color) as color|null + var/new_underwear_color = tgui_color_picker(dressing_human, "Choose your underwear color", "Underwear Color", dressing_human.underwear_color) if(new_underwear_color) dressing_human.underwear_color = sanitize_hexcolor(new_underwear_color) if("Undershirt") diff --git a/code/game/objects/structures/maintenance.dm b/code/game/objects/structures/maintenance.dm index f4017ef0287..0ee8e1b2bcb 100644 --- a/code/game/objects/structures/maintenance.dm +++ b/code/game/objects/structures/maintenance.dm @@ -148,7 +148,7 @@ at the cost of risking a vicious bite.**/ var/altar_result = show_radial_menu(user, src, altar_options, custom_check = CALLBACK(src, PROC_REF(check_menu), user), require_near = TRUE, tooltips = TRUE) switch(altar_result) if("Change Color") - var/chosen_color = input(user, "", "Choose Color", pants_color) as color|null + var/chosen_color = tgui_color_picker(user, "", "Choose Color", pants_color) if(!isnull(chosen_color) && user.can_perform_action(src)) pants_color = chosen_color if("Create Artefact") diff --git a/code/game/objects/structures/mirror.dm b/code/game/objects/structures/mirror.dm index 1423d292d06..0bddf5575d2 100644 --- a/code/game/objects/structures/mirror.dm +++ b/code/game/objects/structures/mirror.dm @@ -207,7 +207,7 @@ MAPPING_DIRECTIONAL_HELPERS(/obj/structure/mirror/broken, 28) race_changer.skin_tone = new_s_tone race_changer.dna.update_ui_block(/datum/dna_block/identity/skin_tone) else if(HAS_TRAIT(race_changer, TRAIT_MUTANT_COLORS) && !HAS_TRAIT(race_changer, TRAIT_FIXED_MUTANT_COLORS)) - var/new_mutantcolor = input(race_changer, "Choose your skin color:", "Race change", race_changer.dna.features[FEATURE_MUTANT_COLOR]) as color|null + var/new_mutantcolor = tgui_color_picker(race_changer, "Choose your skin color:", "Race change", race_changer.dna.features[FEATURE_MUTANT_COLOR]) if(new_mutantcolor && can_use_mirror(race_changer)) var/list/mutant_hsv = rgb2hsv(new_mutantcolor) if(mutant_hsv[3] >= 50) // mutantcolors must be bright @@ -257,7 +257,7 @@ MAPPING_DIRECTIONAL_HELPERS(/obj/structure/mirror/broken, 28) sexy.update_clothing(ITEM_SLOT_ICLOTHING) // update gender shaped clothing /obj/structure/mirror/proc/change_eyes(mob/living/carbon/human/user) - var/new_eye_color = input(user, "Choose your eye color", "Eye Color", user.eye_color_left) as color|null + var/new_eye_color = tgui_color_picker(user, "Choose your eye color", "Eye Color", user.eye_color_left) if(isnull(new_eye_color) || !can_use_mirror(user)) return user.set_eye_color(sanitize_hexcolor(new_eye_color)) @@ -387,14 +387,14 @@ MAPPING_DIRECTIONAL_HELPERS(/obj/structure/mirror/broken, 28) if(hairchoice == "Style") //So you just want to use a mirror then? return ..() - var/new_hair_color = input(user, "Choose your hair color", "Hair Color", user.hair_color) as color|null + var/new_hair_color = tgui_color_picker(user, "Choose your hair color", "Hair Color", user.hair_color) if(!new_hair_color || !can_use_mirror(user)) return if(new_hair_color) user.set_haircolor(sanitize_hexcolor(new_hair_color)) user.dna.update_ui_block(/datum/dna_block/identity/hair_color) if(user.physique == MALE) - var/new_face_color = input(user, "Choose your facial hair color", "Hair Color", user.facial_hair_color) as color|null + var/new_face_color = tgui_color_picker(user, "Choose your facial hair color", "Hair Color", user.facial_hair_color) if(new_face_color && can_use_mirror(user)) user.set_facial_haircolor(sanitize_hexcolor(new_face_color)) user.dna.update_ui_block(/datum/dna_block/identity/facial_color) diff --git a/code/modules/admin/greyscale_modify_menu.dm b/code/modules/admin/greyscale_modify_menu.dm index c87c424661f..7d3710ffb08 100644 --- a/code/modules/admin/greyscale_modify_menu.dm +++ b/code/modules/admin/greyscale_modify_menu.dm @@ -166,12 +166,12 @@ if("pick_color") var/group = params["color_index"] - var/new_color = input( + var/new_color = tgui_color_picker( usr, "Choose color for greyscale color group [group]:", "Greyscale Modification Menu", split_colors[group] - ) as color|null + ) if(new_color) split_colors[group] = new_color queue_refresh() diff --git a/code/modules/admin/verbs/light_debug.dm b/code/modules/admin/verbs/light_debug.dm index 04026573b26..daf012a9b30 100644 --- a/code/modules/admin/verbs/light_debug.dm +++ b/code/modules/admin/verbs/light_debug.dm @@ -256,7 +256,7 @@ GLOBAL_LIST_EMPTY(light_debugged_atoms) if("set_on") parent.set_light(l_on = params["value"]) if("change_color") - var/chosen_color = input(ui.user, "Pick new color", "[parent]", parent.light_color) as color|null + var/chosen_color = tgui_color_picker(ui.user, "Pick new color", "[parent]", parent.light_color) if(chosen_color) parent.set_light(l_color = chosen_color) if("set_power") diff --git a/code/modules/antagonists/abductor/abductor.dm b/code/modules/antagonists/abductor/abductor.dm index 78befca291e..42d3645300b 100644 --- a/code/modules/antagonists/abductor/abductor.dm +++ b/code/modules/antagonists/abductor/abductor.dm @@ -166,7 +166,7 @@ // Keep in mind the darker colors don't look all that great, but it's easier to just reference an existing color list than make a new one var/colorchoice = tgui_input_list(admin, "Select Which Color?", "Alien Spraypainter", GLOB.color_list_ethereal + "Custom Color") if(colorchoice == "Custom Color") - colorchoice = input(admin, "Pick new color", "Alien Spraypainter", COLOR_WHITE) as color|null + colorchoice = tgui_color_picker(admin, "Pick new color", "Alien Spraypainter", COLOR_WHITE) else colorchoice = GLOB.color_list_ethereal[colorchoice] team.team_skincolor = colorchoice diff --git a/code/modules/art/paintings.dm b/code/modules/art/paintings.dm index 8b8ee4a5ebb..1c62bc96cb2 100644 --- a/code/modules/art/paintings.dm +++ b/code/modules/art/paintings.dm @@ -225,7 +225,7 @@ return FALSE //I'd have this done inside the signal, but that'd have to be asynced, //while we want the UI to be updated after the color is chosen, not before. - var/chosen_color = input(user, "Pick new color", painting_implement, params["old_color"]) as color|null + var/chosen_color = tgui_color_picker(user, "Pick new color", painting_implement, params["old_color"]) if(!chosen_color || IS_DEAD_OR_INCAP(user) || !user.is_holding(painting_implement)) return FALSE SEND_SIGNAL(painting_implement, COMSIG_PAINTING_TOOL_PALETTE_COLOR_CHANGED, chosen_color, params["color_index"]) diff --git a/code/modules/client/preferences.dm b/code/modules/client/preferences.dm index 85a889193a5..dd280d120f5 100644 --- a/code/modules/client/preferences.dm +++ b/code/modules/client/preferences.dm @@ -256,12 +256,12 @@ GLOBAL_LIST_EMPTY(preferences_datums) var/default_value = read_preference(requested_preference.type) // Yielding - var/new_color = input( + var/new_color = tgui_color_picker( usr, "Select new color", null, default_value || COLOR_WHITE, - ) as color | null + ) if (!new_color) return FALSE diff --git a/code/modules/client/verbs/ooc.dm b/code/modules/client/verbs/ooc.dm index 1381c3d6b54..6c7fde8e222 100644 --- a/code/modules/client/verbs/ooc.dm +++ b/code/modules/client/verbs/ooc.dm @@ -141,7 +141,7 @@ GLOBAL_VAR_INIT(normal_ooc_colour, "#002eb8") return ADMIN_VERB(set_ooc_color, R_FUN, "Set Player OOC Color", "Modifies the global OOC color.", ADMIN_CATEGORY_SERVER) - var/newColor = input(user, "Please select the new player OOC color.", "OOC color") as color|null + var/newColor = tgui_color_picker(user, "Please select the new player OOC color.", "OOC color") if(isnull(newColor)) return var/new_color = sanitize_color(newColor) diff --git a/code/modules/clothing/head/wig.dm b/code/modules/clothing/head/wig.dm index 9d3f26f875b..42fb32c08cb 100644 --- a/code/modules/clothing/head/wig.dm +++ b/code/modules/clothing/head/wig.dm @@ -51,7 +51,7 @@ /obj/item/clothing/head/wig/attack_self(mob/user) var/new_style = tgui_input_list(user, "Select a hairstyle", "Wig Styling", SSaccessories.hairstyles_list - "Bald") - var/newcolor = adjustablecolor ? input(usr,"","Choose Color",color) as color|null : null + var/newcolor = adjustablecolor ? tgui_color_picker(usr,"","Choose Color",color) : null if(!user.can_perform_action(src)) return if(new_style && new_style != hairstyle) diff --git a/code/modules/library/skill_learning/generic_skillchips/point.dm b/code/modules/library/skill_learning/generic_skillchips/point.dm index 23971af80e0..a8270e3733a 100644 --- a/code/modules/library/skill_learning/generic_skillchips/point.dm +++ b/code/modules/library/skill_learning/generic_skillchips/point.dm @@ -72,7 +72,7 @@ build_all_button_icons(update_flags = UPDATE_BUTTON_ICON, force = TRUE) /datum/action/change_pointer_color/proc/pick_color(mob/user) - var/ncolor = input(owner, "Pick new color", "Pointer Color", arrow_color) as color|null + var/ncolor = tgui_color_picker(owner, "Pick new color", "Pointer Color", arrow_color) if(user != owner || !IsAvailable(feedback = TRUE)) return arrow_color = ncolor diff --git a/code/modules/loadout/categories/pocket.dm b/code/modules/loadout/categories/pocket.dm index 21fc4d32416..860517020b7 100644 --- a/code/modules/loadout/categories/pocket.dm +++ b/code/modules/loadout/categories/pocket.dm @@ -226,7 +226,7 @@ if("select_lipstick_color") var/list/their_loadout = manager.preferences.read_preference(/datum/preference/loadout) var/old_color = their_loadout?[item_path]?[INFO_GREYSCALE] || /obj/item/lipstick::lipstick_color - var/chosen = input(user, "Pick a lipstick color.", "Pick a color", old_color) as color|null + var/chosen = tgui_color_picker(user, "Pick a lipstick color.", "Pick a color", old_color) their_loadout = manager.preferences.read_preference(/datum/preference/loadout) // after sleep: sanity check if(their_loadout?[item_path]) // Validate they still have it equipped their_loadout[item_path][INFO_GREYSCALE] = chosen diff --git a/code/modules/mob/living/basic/guardian/guardian.dm b/code/modules/mob/living/basic/guardian/guardian.dm index 89d5d28a7a4..8b9c14c0b29 100644 --- a/code/modules/mob/living/basic/guardian/guardian.dm +++ b/code/modules/mob/living/basic/guardian/guardian.dm @@ -137,7 +137,7 @@ /mob/living/basic/guardian/proc/guardian_recolour() if (isnull(client)) return - var/chosen_guardian_colour = input(src, "What would you like your colour to be?", "Choose Your Colour", "#ffffff") as color|null + var/chosen_guardian_colour = tgui_color_picker(src, "What would you like your colour to be?", "Choose Your Colour", COLOR_WHITE) if (isnull(chosen_guardian_colour)) //redo proc until we get a color to_chat(src, span_warning("Invalid colour, please try again.")) return guardian_recolour() diff --git a/code/modules/mob/living/basic/space_fauna/space_dragon/space_dragon.dm b/code/modules/mob/living/basic/space_fauna/space_dragon/space_dragon.dm index 45d023ce744..e8ebb18a47a 100644 --- a/code/modules/mob/living/basic/space_fauna/space_dragon/space_dragon.dm +++ b/code/modules/mob/living/basic/space_fauna/space_dragon/space_dragon.dm @@ -140,7 +140,7 @@ /// Select scale colour with the colour picker /mob/living/basic/space_dragon/proc/select_colour() - chosen_colour = input(src, "What colour would you like to be?" ,"Colour Selection", COLOR_WHITE) as color|null + chosen_colour = tgui_color_picker(src, "What colour would you like to be?" ,"Colour Selection", COLOR_WHITE) if(!chosen_colour) // Redo proc until we get a color to_chat(src, span_warning("Not a valid colour, please try again.")) select_colour() diff --git a/code/modules/mob/living/living.dm b/code/modules/mob/living/living.dm index d8d5dea9065..fb155e0e419 100644 --- a/code/modules/mob/living/living.dm +++ b/code/modules/mob/living/living.dm @@ -2906,7 +2906,7 @@ GLOBAL_LIST_EMPTY(fire_appearances) if(picked_theme == "Random") picked_theme = null //holopara code handles not having a theme by giving a random one var/picked_name = tgui_input_text(admin, "Name the guardian, leave empty to let player name it.", "Guardian Controller", max_length = MAX_NAME_LEN) - var/picked_color = input(admin, "Set the guardian's color, cancel to let player set it.", "Guardian Controller", "#ffffff") as color|null + var/picked_color = tgui_color_picker(admin, "Set the guardian's color, cancel to let player set it.", "Guardian Controller", COLOR_WHITE) if(tgui_alert(admin, "Confirm creation.", "Guardian Controller", list("Yes", "No")) != "Yes") return var/mob/living/basic/guardian/summoned_guardian = new picked_type(src, picked_theme) diff --git a/code/modules/mod/modules/modules_general.dm b/code/modules/mod/modules/modules_general.dm index 8cd642fc9c9..5cbe35c77d0 100644 --- a/code/modules/mod/modules/modules_general.dm +++ b/code/modules/mod/modules/modules_general.dm @@ -476,7 +476,7 @@ /obj/item/mod/module/flashlight/configure_edit(key, value) switch(key) if("light_color") - value = input(usr, "Pick new light color", "Flashlight Color") as color|null + value = tgui_color_picker(usr, "Pick new light color", "Flashlight Color") if(!value) return if(is_color_dark(value, 50)) diff --git a/code/modules/modular_computers/computers/item/computer_ui.dm b/code/modules/modular_computers/computers/item/computer_ui.dm index 16a0a5915ff..bd221463017 100644 --- a/code/modules/modular_computers/computers/item/computer_ui.dm +++ b/code/modules/modular_computers/computers/item/computer_ui.dm @@ -176,7 +176,7 @@ var/mob/user = usr var/new_color while(!new_color) - new_color = input(user, "Choose a new color for [src]'s flashlight.", "Light Color",light_color) as color|null + new_color = tgui_color_picker(user, "Choose a new color for [src]'s flashlight.", "Light Color",light_color) if(!new_color) return if(is_color_dark(new_color, 50) ) //Colors too dark are rejected diff --git a/code/modules/projectiles/boxes_magazines/_box_magazine.dm b/code/modules/projectiles/boxes_magazines/_box_magazine.dm index bcc551bdd17..355ce2cb530 100644 --- a/code/modules/projectiles/boxes_magazines/_box_magazine.dm +++ b/code/modules/projectiles/boxes_magazines/_box_magazine.dm @@ -198,7 +198,7 @@ if(!ammo_band_icon) balloon_alert(user, "no indicator support!") return - var/new_color = input(user, "Set a new ammo band color, cancel to remove indicator", "Ammo Box Indicator Color", ammo_band_color) as color|null + var/new_color = tgui_color_picker(user, "Set a new ammo band color, cancel to remove indicator", "Ammo Box Indicator Color", ammo_band_color) ammo_band_color = new_color balloon_alert(user, "indicator updated") update_appearance() diff --git a/code/modules/projectiles/guns/energy/kinetic_accelerator.dm b/code/modules/projectiles/guns/energy/kinetic_accelerator.dm index 0e0f79a6bcb..35793594c59 100644 --- a/code/modules/projectiles/guns/energy/kinetic_accelerator.dm +++ b/code/modules/projectiles/guns/energy/kinetic_accelerator.dm @@ -704,5 +704,5 @@ /obj/item/borg/upgrade/modkit/tracer/adjustable/proc/choose_bolt_color(mob/user) set waitfor = FALSE - var/new_color = input(user,"","Choose Color",bolt_color) as color|null + var/new_color = tgui_color_picker(user, "", "Choose Color", bolt_color) bolt_color = new_color || bolt_color diff --git a/code/modules/research/xenobiology/crossbreeding/_clothing.dm b/code/modules/research/xenobiology/crossbreeding/_clothing.dm index bd91fa7f9e2..fbcef4a6d81 100644 --- a/code/modules/research/xenobiology/crossbreeding/_clothing.dm +++ b/code/modules/research/xenobiology/crossbreeding/_clothing.dm @@ -73,7 +73,7 @@ Slimecrossing Armor /datum/action/item_action/change_prism_colour/do_effect(trigger_flags) var/obj/item/clothing/glasses/prism_glasses/glasses = target - var/new_color = input(owner, "Choose the lens color:", "Color change",glasses.glasses_color) as color|null + var/new_color = tgui_color_picker(owner, "Choose the lens color:", "Color change",glasses.glasses_color) if(!new_color) return RemoveElement(/datum/element/wearable_client_colour, /datum/client_colour/glass_colour, ITEM_SLOT_EYES, GLASSES_TRAIT, glasses.glasses_color, glasses.forced_glass_color) diff --git a/code/modules/research/xenobiology/crossbreeding/prismatic.dm b/code/modules/research/xenobiology/crossbreeding/prismatic.dm index 647711192af..0f35588ebd5 100644 --- a/code/modules/research/xenobiology/crossbreeding/prismatic.dm +++ b/code/modules/research/xenobiology/crossbreeding/prismatic.dm @@ -115,7 +115,7 @@ Prismatic extracts: colour = SLIME_TYPE_RAINBOW /obj/item/slimecross/prismatic/rainbow/attack_self(mob/user) - var/newcolor = input(user, "Choose the slime color:", "Color change",paintcolor) as color|null + var/newcolor = tgui_color_picker(user, "Choose the slime color:", "Color change", paintcolor) if(user.get_active_held_item() != src || user.stat != CONSCIOUS || HAS_TRAIT(user, TRAIT_HANDS_BLOCKED)) return if(!newcolor) diff --git a/code/modules/surgery/organs/internal/eyes/_eyes.dm b/code/modules/surgery/organs/internal/eyes/_eyes.dm index da9584988ef..38d2f3237b8 100644 --- a/code/modules/surgery/organs/internal/eyes/_eyes.dm +++ b/code/modules/surgery/organs/internal/eyes/_eyes.dm @@ -878,12 +878,12 @@ set_beam_range(new_range) return TRUE if("pick_color") - var/new_color = input( + var/new_color = tgui_color_picker( usr, "Choose eye color color:", "High Luminosity Eyes Menu", light_color_string - ) as color|null + ) if(new_color) var/to_update = params["to_update"] set_beam_color(new_color, to_update) diff --git a/code/modules/tgui_input/color.dm b/code/modules/tgui_input/color.dm new file mode 100644 index 00000000000..e418fb9e259 --- /dev/null +++ b/code/modules/tgui_input/color.dm @@ -0,0 +1,123 @@ +/** + * Creates a TGUI color picker window and returns the user's response. + * + * This proc should be used to create a color picker that the caller will wait for a response from. + * Arguments: + * * user - The user to show the picker to. + * * title - The of the picker modal, shown on the top of the TGUI window. + * * timeout - The timeout of the picker, after which the modal will close and qdel itself. Set to zero for no timeout. + * * autofocus - The bool that controls if this picker should grab window focus. + */ +/proc/tgui_color_picker(mob/user, message, title, default = "#000000", timeout = 0, autofocus = TRUE) + if (!user) + user = usr + if (!istype(user)) + if (istype(user, /client)) + var/client/client = user + user = client.mob + else + return + // Client does NOT have tgui_input on: Returns regular input + if(!user.client.prefs.read_preference(/datum/preference/toggle/tgui_input)) + return input(user, message, title, default) as color|null + var/datum/tgui_color_picker/picker = new(user, message, title, default, timeout, autofocus) + picker.ui_interact(user) + picker.wait() + if (picker) + . = picker.choice + qdel(picker) + +/** + * # tgui_color_picker + * + * Datum used for instantiating and using a TGUI-controlled color picker. + */ +/datum/tgui_color_picker + /// The title of the TGUI window + var/title + /// The message to show the user + var/message + /// The default choice, used if there is an existing value + var/default + /// The color the user selected, null if no selection has been made + var/choice + /// The time at which the tgui_color_picker was created, for displaying timeout progress. + var/start_time + /// The lifespan of the tgui_color_picker, after which the window will close and delete itself. + var/timeout + /// The bool that controls if this modal should grab window focus + var/autofocus + /// Boolean field describing if the tgui_color_picker was closed by the user. + var/closed + +/datum/tgui_color_picker/New(mob/user, message, title, default, timeout, autofocus) + src.autofocus = autofocus + src.title = title + src.default = default + src.message = message + if (timeout) + src.timeout = timeout + start_time = world.time + QDEL_IN(src, timeout) + +/datum/tgui_color_picker/Destroy(force) + SStgui.close_uis(src) + return ..() + +/** + * Waits for a user's response to the tgui_color_picker's prompt before returning. Returns early if + * the window was closed by the user. + */ +/datum/tgui_color_picker/proc/wait() + while (!choice && !closed && !QDELETED(src)) + stoplag(1) + +/datum/tgui_color_picker/ui_interact(mob/user, datum/tgui/ui) + ui = SStgui.try_update_ui(user, src, ui) + if(!ui) + ui = new(user, src, "ColorPickerModal") + ui.open() + ui.set_autoupdate(timeout > 0) + +/datum/tgui_color_picker/ui_close(mob/user) + . = ..() + closed = TRUE + +/datum/tgui_color_picker/ui_state(mob/user) + return GLOB.always_state + +/datum/tgui_color_picker/ui_static_data(mob/user) + . = list() + .["autofocus"] = autofocus + .["large_buttons"] = !user.client?.prefs || user.client.prefs.read_preference(/datum/preference/toggle/tgui_input_large) + .["swapped_buttons"] = !user.client?.prefs || user.client.prefs.read_preference(/datum/preference/toggle/tgui_input_swapped) + .["title"] = title + .["default_color"] = default + .["message"] = message + +/datum/tgui_color_picker/ui_data(mob/user) + . = list() + if(timeout) + .["timeout"] = CLAMP01((timeout - (world.time - start_time) - 1 SECONDS) / (timeout - 1 SECONDS)) + +/datum/tgui_color_picker/ui_act(action, list/params) + . = ..() + if (.) + return + switch(action) + if("submit") + var/raw_data = LOWER_TEXT(params["entry"]) + var/hex = sanitize_hexcolor(raw_data, desired_format = 6, include_crunch = TRUE) + if (!hex) + return + set_choice(hex) + closed = TRUE + SStgui.close_uis(src) + return TRUE + if("cancel") + closed = TRUE + SStgui.close_uis(src) + return TRUE + +/datum/tgui_color_picker/proc/set_choice(choice) + src.choice = choice diff --git a/tgstation.dme b/tgstation.dme index 89193e5f27d..508b18f8f8f 100644 --- a/tgstation.dme +++ b/tgstation.dme @@ -6459,6 +6459,7 @@ #include "code\modules\tgui\states\zlevel.dm" #include "code\modules\tgui_input\alert.dm" #include "code\modules\tgui_input\checkboxes.dm" +#include "code\modules\tgui_input\color.dm" #include "code\modules\tgui_input\keycombo.dm" #include "code\modules\tgui_input\list.dm" #include "code\modules\tgui_input\number.dm" diff --git a/tgui/packages/tgui/interfaces/ColorPickerModal/Color.tsx b/tgui/packages/tgui/interfaces/ColorPickerModal/Color.tsx new file mode 100644 index 00000000000..e9eba731b84 --- /dev/null +++ b/tgui/packages/tgui/interfaces/ColorPickerModal/Color.tsx @@ -0,0 +1,334 @@ +/** + * @file + * @copyright 2023 itsmeow + * @license MIT + */ +import React, { useMemo, useRef } from 'react'; +import { + type HsvaColor, + hexToHsva, + hsvaToHslString, + hsvaToRgba, + rgbaToHsva, +} from 'tgui-core/color'; +import { Box, Button, type Interaction, Interactive, Pointer, Stack } from 'tgui-core/components'; +import { clamp } from 'tgui-core/math'; +import { classes } from 'tgui-core/react'; +import { colorList } from './ColorPresets'; + +interface ColorPresetsProps { + setColor: (color: HsvaColor) => void; + setShowPresets: (show: boolean) => void; +} + +export const ColorPresets: React.FC = React.memo( + ({ setColor, setShowPresets }) => { + return ( + <> + + + + {colorList.map((row, index) => ( + + + {row.map((entry) => ( + + setColor(hexToHsva(entry))} + > + + + + ))} + + + ))} + + + + ); + }, +); + +interface SaturationValueProps { + hsva: HsvaColor; + onChange: (newColor: Partial) => void; +} + +export const SaturationValue: React.FC = React.memo( + ({ hsva, onChange }) => { + const handleMove = (interaction: Interaction) => { + onChange({ + s: interaction.left * 100, + v: 100 - interaction.top * 100, + }); + }; + + const handleKey = (offset: Interaction) => { + onChange({ + s: clamp(hsva.s + offset.left * 100, 0, 100), + v: clamp(hsva.v - offset.top * 100, 0, 100), + }); + }; + + const containerStyle = useMemo( + () => ({ + backgroundColor: hsvaToHslString({ + h: hsva.h, + s: 100, + v: 100, + a: 1, + }), + }), + [hsva.h], + ); + + const containerRef = useRef(null); + + return ( +
+ + + +
+ ); + }, +); + +interface HueProps { + className?: string; + hue: number; + onChange: (newHue: Partial) => void; +} + +export const Hue: React.FC = React.memo( + ({ className, hue, onChange }) => { + const handleMove = (interaction: Interaction) => { + onChange({ h: 360 * interaction.left }); + }; + + const handleKey = (offset: Interaction) => { + onChange({ h: clamp(hue + offset.left * 360, 0, 360) }); + }; + + const nodeClassName = classes(['react-colorful__hue', className]); + const containerRef = useRef(null); + + return ( +
+ + + +
+ ); + }, +); + +interface SaturationProps { + className?: string; + color: HsvaColor; + onChange: (newSaturation: Partial) => void; +} + +export const Saturation: React.FC = React.memo( + ({ className, color, onChange }) => { + const handleMove = (interaction: Interaction) => { + onChange({ s: 100 * interaction.left }); + }; + + const handleKey = (offset: Interaction) => { + onChange({ s: clamp(color.s + offset.left * 100, 0, 100) }); + }; + + const nodeClassName = classes(['react-colorful__saturation', className]); + + const background = useMemo( + () => + `linear-gradient(to right, ${hsvaToHslString({ + h: color.h, + s: 0, + v: color.v, + a: 1, + })}, ${hsvaToHslString({ h: color.h, s: 100, v: color.v, a: 1 })})`, + [color], + ); + const containerRef = useRef(null); + + return ( +
+ + + +
+ ); + }, +); + +interface ValueProps { + className?: string; + color: HsvaColor; + onChange: (newValue: Partial) => void; +} + +export const Value: React.FC = React.memo( + ({ className, color, onChange }) => { + const handleMove = (interaction: Interaction) => { + onChange({ v: 100 * interaction.left }); + }; + + const handleKey = (offset: Interaction) => { + onChange({ + v: clamp(color.v + offset.left * 100, 0, 100), + }); + }; + + const nodeClassName = classes(['react-colorful__value', className]); + + const background = useMemo( + () => + `linear-gradient(to right, ${hsvaToHslString({ + h: color.h, + s: color.s, + v: 0, + a: 1, + })}, ${hsvaToHslString({ h: color.h, s: color.s, v: 100, a: 1 })})`, + [color], + ); + const containerRef = useRef(null); + + return ( +
+ + + +
+ ); + }, +); + +interface RGBSliderProps { + className?: string; + color: HsvaColor; + onChange: (newValue: HsvaColor) => void; + target: 'r' | 'g' | 'b'; +} + +export const RGBSlider: React.FC = React.memo( + ({ className, color, onChange, target }) => { + const rgb = hsvaToRgba(color); + + const setNewTarget = (value: number) => { + const newRgb = { ...rgb, [target]: value }; + onChange(rgbaToHsva(newRgb)); + }; + + const handleMove = (interaction: Interaction) => { + setNewTarget(255 * interaction.left); + }; + + const handleKey = (offset: Interaction) => { + setNewTarget(clamp(rgb[target] + offset.left * 255, 0, 255)); + }; + + const nodeClassName = classes([`react-colorful__${target}`, className]); + + const channels = { + r: `rgb(${Math.round(rgb.r)},0,0)`, + g: `rgb(0,${Math.round(rgb.g)},0)`, + b: `rgb(0,0,${Math.round(rgb.b)})`, + }; + + const selected = channels[target]; + const containerRef = useRef(null); + + return ( +
+ + + +
+ ); + }, +); diff --git a/tgui/packages/tgui/interfaces/ColorPickerModal/ColorPresets.tsx b/tgui/packages/tgui/interfaces/ColorPickerModal/ColorPresets.tsx new file mode 100644 index 00000000000..1384b5251f2 --- /dev/null +++ b/tgui/packages/tgui/interfaces/ColorPickerModal/ColorPresets.tsx @@ -0,0 +1,210 @@ +// Used for the colour picker, and anything else that wants a list of preset colours. +export const colorList = [ + [ + '003366', + '336699', + '3366CC', + '003399', + '000099', + '0000CC', + '000066', + ], + [ + '006666', + '006699', + '0099CC', + '0066CC', + '0033CC', + '0000FF', + '3333FF', + '333399', + ], + [ + '008080', + '009999', + '33CCCC', + '00CCFF', + '0099FF', + '0066FF', + '3366FF', + '3333CC', + '666699', + ], + [ + '339966', + '00CC99', + '00FFCC', + '00FFFF', + '33CCFF', + '3399FF', + '6699FF', + '6666FF', + '6600FF', + '6600CC', + ], + [ + '339933', + '00CC66', + '00FF99', + '66FFCC', + '66FFFF', + '66CCFF', + '99CCFF', + '9999FF', + '9966FF', + '9933FF', + '9900FF', + ], + [ + '006600', + '00CC00', + '00FF00', + '66FF99', + '99FFCC', + 'CCFFFF', + 'CCECFF', + 'CCCCFF', + 'CC99FF', + 'CC66FF', + 'CC00FF', + '9900CC', + ], + [ + '003300', + '008000', + '33CC33', + '66FF66', + '99FF99', + 'CCFFCC', + 'FFFFFF', + 'FFCCFF', + 'FF99FF', + 'FF66FF', + 'FF00FF', + 'CC00CC', + '660066', + ], + [ + '336600', + '009900', + '66FF33', + '99FF66', + 'CCFF99', + 'FFFFCC', + 'FFCCCC', + 'FF99CC', + 'FF66CC', + 'FF33CC', + 'CC0099', + '800080', + ], + [ + '333300', + '669900', + '99FF33', + 'CCFF66', + 'FFFF99', + 'FFCC99', + 'FF9999', + 'FF6699', + 'FF3399', + 'CC3399', + '990099', + ], + [ + '666633', + '99CC00', + 'CCFF33', + 'FFFF66', + 'FFCC66', + 'FF9966', + 'FF7C80', + 'FF0066', + 'D60093', + '993366', + ], + [ + '808000', + 'CCCC00', + 'FFFF00', + 'FFCC00', + 'FF9933', + 'FF6600', + 'FF5050', + 'CC0066', + '660033', + ], + [ + '996633', + 'CC9900', + 'FF9900', + 'CC6600', + 'FF3300', + 'FF0000', + 'CC0000', + '990033', + ], + [ + '663300', + '996600', + 'CC3300', + '993300', + '990000', + '800000', + 'A50021', + ], + [ + 'F8F8F8', + 'DDDDDD', + 'B2B2B2', + '808080', + '5F5F5F', + '333333', + '1C1C1C', + '080808', + ], + [ + 'FFFFFF', + 'EAEAEA', + 'C0C0C0', + '969696', + '777777', + '4D4D4D', + '292929', + '111111', + '000000', + ], + [ + 'f0197d', + 'ff7f50', + 'ffe45e', + '21fa90', + '7df9ff', + '2ccaff', + '21649f', + '7b55dd', + 'b81fff', + 'ff5cad', + ], + [ + 'ffe2db', + 'ffd5cc', + 'feb8a0', + 'eaa78d', + 'e7a992', + 'd49487', + 'facca4', + 'e8b782', + 'ffc905', + ], + [ + 'c48c5e', + 'bd7740', + 'ab7968', + '8c553f', + '755246', + '86655b', + '754223', + '471b18', + ], +]; diff --git a/tgui/packages/tgui/interfaces/ColorPickerModal/ColorSetter.tsx b/tgui/packages/tgui/interfaces/ColorPickerModal/ColorSetter.tsx new file mode 100644 index 00000000000..5ff57bcf161 --- /dev/null +++ b/tgui/packages/tgui/interfaces/ColorPickerModal/ColorSetter.tsx @@ -0,0 +1,285 @@ +/** + * @file + * @copyright 2023 itsmeow + * @license MIT + */ +import React, { useCallback, useState } from 'react'; +import { + type HsvaColor, + hexToHsva, + hsvaToHex, + hsvaToRgba, + rgbaToHsva, +} from 'tgui-core/color'; +import { Box, Button, Stack, Tooltip } from 'tgui-core/components'; +import { InputButtons } from '../common/InputButtons'; +import { + ColorPresets, + Hue, + RGBSlider, + Saturation, + SaturationValue, + Value, +} from './Color'; +import { HexColorInput, TextSetter } from './TextSetter'; + +interface ColorSelectorProps { + color: HsvaColor; + setColor: React.Dispatch>; + defaultColor: string; +} + +export const ColorSelector: React.FC = React.memo( + ({ color, setColor, defaultColor }) => { + const handleChange = useCallback( + (params: Partial) => { + setColor((current) => ({ ...current, ...params })); + }, + [setColor], + ); + + const [showPresets, setShowPresets] = useState(false); + const rgb = hsvaToRgba(color); + const hexColor = hsvaToHex(color); + + return ( + + + + +
+ + +
+
+ + + New + + + Current + +
+ + + + + + +
+ + + +
+
+ + {showPresets ? ( + handleChange(c)} + setShowPresets={setShowPresets} + /> + ) : ( + + + + + Hex: + + + { + setColor(hexToHsva(value)); + }} + /> + + + + + + + + + + + + + + + + )} + +
+ ); + }, +); + +interface RowProps { + color: HsvaColor; + handleChange: (c: Partial) => void; +} + +const HueRow: React.FC = React.memo(({ color, handleChange }) => ( + + + + H: + + + + + + handleChange({ h: v })} + max={360} + unit="°" + /> + + + +)); + +const SaturationRow: React.FC = React.memo( + ({ color, handleChange }) => ( + + + + S: + + + + + + handleChange({ s: v })} + unit="%" + /> + + + + ), +); + +const ValueRow: React.FC = React.memo(({ color, handleChange }) => ( + + + + V: + + + + + + handleChange({ v })} + unit="%" + /> + + + +)); + +interface RGBRowProps { + color: HsvaColor; + handleChange: (c: HsvaColor) => void; +} + +const RedRow: React.FC = React.memo(({ color, handleChange }) => { + const rgb = hsvaToRgba(color); + return ( + + + + R: + + + + + + { + handleChange(rgbaToHsva({ ...rgb, r: v })); + }} + max={255} + /> + + + + ); +}); + +const GreenRow: React.FC = React.memo( + ({ color, handleChange }) => { + const rgb = hsvaToRgba(color); + return ( + + + + G: + + + + + + { + handleChange(rgbaToHsva({ ...rgb, g: v })); + }} + max={255} + /> + + + + ); + }, +); + +const BlueRow: React.FC = React.memo(({ color, handleChange }) => { + const rgb = hsvaToRgba(color); + return ( + + + + B: + + + + + + { + handleChange(rgbaToHsva({ ...rgb, b: v })); + }} + max={255} + /> + + + + ); +}); diff --git a/tgui/packages/tgui/interfaces/ColorPickerModal/TextSetter.tsx b/tgui/packages/tgui/interfaces/ColorPickerModal/TextSetter.tsx new file mode 100644 index 00000000000..839fb568b7f --- /dev/null +++ b/tgui/packages/tgui/interfaces/ColorPickerModal/TextSetter.tsx @@ -0,0 +1,108 @@ +/** + * @file + * @copyright 2023 itsmeow + * @license MIT + */ +import React, { useCallback, useEffect, useMemo, useState } from 'react'; +import { validHex } from 'tgui-core/color'; +import { Input, NumberInput } from 'tgui-core/components'; + +interface TextSetterProps { + value: number; + callback: (value: number) => void; + min?: number; + max?: number; + unit?: string; +} + +export const TextSetter: React.FC = React.memo( + ({ value, callback, min = 0, max = 100, unit }) => { + return ( + + ); + }, +); + +interface HexColorInputProps { + prefixed?: boolean; + alpha?: boolean; + color: string; + fluid?: boolean; + onChange: (newColor: string) => void; +} + +export const HexColorInput: React.FC = React.memo( + ({ alpha, color, fluid, onChange, ...rest }) => { + const initialColor = useMemo(() => { + const stripped = color + .replace(/[^0-9A-Fa-f]/g, '') + .substring(0, 6) + .toUpperCase(); + return stripped; + }, [color]); + + const [localValue, setLocalValue] = useState(initialColor); + + useEffect(() => { + setLocalValue(initialColor); + }, [initialColor]); + + const isValidFullHex = useCallback( + (val: string) => { + return validHex(val, alpha) && val.length === 6; + }, + [alpha], + ); + + const handleChangeEvent = (value: string) => { + const strippedValue = value + .replace(/[^0-9A-Fa-f]/g, '') + .substring(0, 6) + .toUpperCase(); + + setLocalValue(strippedValue); + + if (isValidFullHex(strippedValue)) { + onChange(strippedValue); + } + }; + + const commitOrRevert = useCallback(() => { + if (isValidFullHex(localValue)) { + onChange(localValue); + } else { + setLocalValue(initialColor); + } + }, [initialColor, isValidFullHex, localValue, onChange]); + + const handleBlur = () => { + commitOrRevert(); + }; + + const handleKeyDown = (e: React.KeyboardEvent) => { + if (e.key === 'Enter') { + commitOrRevert(); + (e.currentTarget as HTMLInputElement).blur(); + } + }; + + return ( + + ); + }, +); diff --git a/tgui/packages/tgui/interfaces/ColorPickerModal/index.tsx b/tgui/packages/tgui/interfaces/ColorPickerModal/index.tsx new file mode 100644 index 00000000000..5a3f0ebd50c --- /dev/null +++ b/tgui/packages/tgui/interfaces/ColorPickerModal/index.tsx @@ -0,0 +1,78 @@ +/** + * @file + * @copyright 2023 itsmeow + * @license MIT + */ +import type React from 'react'; +import { useEffect, useState } from 'react'; +import { type HsvaColor, hexToHsva } from 'tgui-core/color'; +import { Autofocus, Box, Section, Stack } from 'tgui-core/components'; +import { useBackend } from '../../backend'; +import { Window } from '../../layouts'; +import { Loader } from '../common/Loader'; +import { ColorSelector } from './ColorSetter'; + +interface ColorPickerData { + autofocus: boolean; + buttons: string[]; + message: string; + large_buttons: boolean; + swapped_buttons: boolean; + timeout: number; + title: string; + default_color: string; +} + +type ColorPickerModalProps = any; + +export const ColorPickerModal: React.FC = () => { + const { data } = useBackend(); + const { timeout, message, autofocus, default_color = '#000000' } = data; + let { title } = data; + + const [selectedColor, setSelectedColor] = useState( + hexToHsva(default_color), + ); + + useEffect(() => { + setSelectedColor(hexToHsva(default_color)); + }, [default_color]); + + if (!title) { + title = 'Colour Editor'; + } + + return ( + + {!!timeout && } + + + {!!autofocus && } + {message && ( + +
+ + {message} + +
+
+ )} + +
+ +
+
+
+
+
+ ); +}; diff --git a/tgui/packages/tgui/styles/interfaces/ColorPicker.scss b/tgui/packages/tgui/styles/interfaces/ColorPicker.scss new file mode 100644 index 00000000000..f9d9d317695 --- /dev/null +++ b/tgui/packages/tgui/styles/interfaces/ColorPicker.scss @@ -0,0 +1,150 @@ +/** + * MIT License + * https://github.com/omgovich/react-colorful/ + * + * Copyright (c) 2020 Vlad Shilov + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +@use '../colors.scss'; +@use '../base.scss'; + +.react-colorful { + position: relative; + display: flex; + flex-direction: column; + width: 200px; + height: 200px; + user-select: none; + cursor: default; +} + +.react-colorful__saturation_value { + position: relative; + flex-grow: 1; + border-color: transparent; /* Fixes https://github.com/omgovich/react-colorful/issues/139 */ + border-bottom: 12px solid #000; + border-radius: 8px 8px 0 0; + background-image: + linear-gradient(to top, rgba(0, 0, 0, 255), rgba(0, 0, 0, 0)), + linear-gradient(to right, rgba(255, 255, 255, 255), rgba(255, 255, 255, 0)); +} + +.react-colorful__pointer-fill, +.react-colorful__alpha-gradient { + content: ''; + position: absolute; + left: 0; + top: 0; + right: 0; + bottom: 0; + pointer-events: none; + border-radius: inherit; +} + +/* Improve elements rendering on light backgrounds */ +.react-colorful__alpha-gradient, +.react-colorful__saturation_value { + box-shadow: inset 0 0 0 1px rgba(0, 0, 0, 0.05); +} + +.react-colorful__hue, +.react-colorful__r, +.react-colorful__g, +.react-colorful__b, +.react-colorful__alpha, +.react-colorful__saturation, +.react-colorful__value { + position: relative; + height: 24px; +} + +.react-colorful__hue { + background: linear-gradient( + to right, + #f00 0%, + #ff0 17%, + #0f0 33%, + #0ff 50%, + #00f 67%, + #f0f 83%, + #f00 100% + ); +} + +.react-colorful__r { + background: linear-gradient(to right, #000, #f00); +} + +.react-colorful__g { + background: linear-gradient(to right, #000, #0f0); +} + +.react-colorful__b { + background: linear-gradient(to right, #000, #00f); +} + +/* Round bottom corners of the last element: `Hue` for `ColorPicker` or `Alpha` for `AlphaColorPicker` */ +.react-colorful__last-control { + border-radius: 0 0 8px 8px; +} + +.react-colorful__interactive { + position: absolute; + left: 0; + top: 0; + right: 0; + bottom: 0; + border-radius: inherit; + outline: none; + /* Don't trigger the default scrolling behavior when the event is originating from this element */ + touch-action: none; +} + +.react-colorful__pointer { + position: absolute; + z-index: 1; + box-sizing: border-box; + width: 28px; + height: 28px; + transform: translate(-50%, -50%); + background-color: #cfcfcf; + border: 2px solid #cfcfcf; + border-radius: 50%; + box-shadow: 0 2px 5px rgba(0, 0, 0, 0.4); +} + +.react-colorful__interactive:focus .react-colorful__pointer { + transform: translate(-50%, -50%) scale(1.1); + background-color: #fff; + border-color: #fff; +} + +/* Chessboard-like pattern for alpha related elements */ +.react-colorful__alpha, +.react-colorful__alpha-pointer { + background-color: #fff; + background-image: url('data:image/svg+xml,'); +} + +.react-colorful__saturation-pointer, +.react-colorful__value-pointer, +.react-colorful__hue-pointer, +.react-colorful__r-pointer, +.react-colorful__g-pointer, +.react-colorful__b-pointer { + z-index: 1; + width: 20px; + height: 20px; +} + +/* Display the saturation value pointer over the hue one */ +.react-colorful__saturation_value-pointer { + z-index: 3; +} diff --git a/tgui/packages/tgui/styles/main.scss b/tgui/packages/tgui/styles/main.scss index 75ec833cc02..fc248f950e1 100644 --- a/tgui/packages/tgui/styles/main.scss +++ b/tgui/packages/tgui/styles/main.scss @@ -44,6 +44,7 @@ @include meta.load-css('./interfaces/Trophycase.scss'); @include meta.load-css('./interfaces/Uplink.scss'); @include meta.load-css('./interfaces/DetectiveBoard.scss'); +@include meta.load-css('./interfaces/ColorPicker.scss'); // Layouts @include meta.load-css('./layouts/Layout.scss');