diff --git a/code/modules/paperwork/folders.dm b/code/modules/paperwork/folders.dm
index 532edb88d3d..d4162761fc5 100644
--- a/code/modules/paperwork/folders.dm
+++ b/code/modules/paperwork/folders.dm
@@ -6,55 +6,16 @@
w_class = WEIGHT_CLASS_SMALL
pressure_resistance = 2
resistance_flags = FLAMMABLE
+ /// The background color for tgui in hex (with a `#`)
+ var/bg_color = "#7f7f7f"
/obj/item/folder/suicide_act(mob/living/user)
user.visible_message("[user] begins filing an imaginary death warrant! It looks like [user.p_theyre()] trying to commit suicide!")
return OXYLOSS
-/obj/item/folder/blue
- desc = "A blue folder."
- icon_state = "folder_blue"
-
-/obj/item/folder/red
- desc = "A red folder."
- icon_state = "folder_red"
-
-/obj/item/folder/yellow
- desc = "A yellow folder."
- icon_state = "folder_yellow"
-
-/obj/item/folder/white
- desc = "A white folder."
- icon_state = "folder_white"
-
-
-/obj/item/folder/update_overlays()
+/obj/item/folder/Initialize()
+ update_icon()
. = ..()
- if(contents.len)
- . += "folder_paper"
-
-
-/obj/item/folder/attackby(obj/item/W, mob/user, params)
- if(burn_paper_product_attackby_check(W, user))
- return
- if(istype(W, /obj/item/paper) || istype(W, /obj/item/photo) || istype(W, /obj/item/documents))
- if(!user.transferItemToLoc(W, src))
- return
- to_chat(user, "You put [W] into [src].")
- update_appearance()
- else if(istype(W, /obj/item/pen))
- if(!user.is_literate())
- to_chat(user, "You scribble illegibly on the cover of [src]!")
- return
-
- var/inputvalue = stripped_input(user, "What would you like to label the folder?", "Folder Labelling", "", MAX_NAME_LEN)
-
- if(!inputvalue)
- return
-
- if(user.canUseTopic(src, BE_CLOSE))
- name = "folder[(inputvalue ? " - '[inputvalue]'" : null)]"
-
/obj/item/folder/Destroy()
for(var/obj/important_thing in contents)
@@ -63,70 +24,96 @@
important_thing.forceMove(drop_location()) //don't destroy round critical content such as objective documents.
return ..()
+/obj/item/folder/examine()
+ . = ..()
+ if(contents)
+ . += "Alt-click to remove [contents[1]]."
+
+/obj/item/folder/proc/rename(mob/user)
+ if(!user.is_literate())
+ to_chat(user, "You scribble illegibly on the cover of [src]!")
+ return
+
+ var/inputvalue = stripped_input(user, "What would you like to label the folder?", "Folder Labelling", "", MAX_NAME_LEN)
+
+ if(!inputvalue)
+ return
+
+ if(user.canUseTopic(src, BE_CLOSE))
+ name = "folder[(inputvalue ? " - '[inputvalue]'" : null)]"
+
+/obj/item/folder/proc/remove_item(obj/item/Item, mob/user)
+ if(istype(Item))
+ Item.forceMove(user.loc)
+ user.put_in_hands(Item)
+ to_chat(user, "You remove [Item] from [src].")
+ update_icon()
+
+/obj/item/folder/AltClick(mob/user)
+ ..()
+ if(contents)
+ remove_item(contents[1], user)
+
+/obj/item/folder/update_overlays()
+ . = ..()
+ if(contents.len)
+ . += "folder_paper"
+
+/obj/item/folder/attackby(obj/item/weapon, mob/user, params)
+ if(burn_paper_product_attackby_check(weapon, user))
+ return
+ if(istype(weapon, /obj/item/paper) || istype(weapon, /obj/item/photo) || istype(weapon, /obj/item/documents))
+ //Add paper, photo or documents into the folder
+ if(!user.transferItemToLoc(weapon, src))
+ return
+ to_chat(user, "You put [weapon] into [src].")
+ update_appearance()
+ else if(istype(weapon, /obj/item/pen))
+ rename(user)
/obj/item/folder/attack_self(mob/user)
- var/dat = "
[name]"
-
- for(var/obj/item/I in src)
- dat += "Remove - [I.name]
"
- user << browse(dat, "window=folder")
- onclose(user, "folder")
add_fingerprint(usr)
+ ui_interact(user)
+ return
+/obj/item/folder/ui_interact(mob/user, datum/tgui/ui)
+ ui = SStgui.try_update_ui(user, src, ui)
+ if(!ui)
+ ui = new(user, src, "Folder")
+ ui.open()
+
+/obj/item/folder/ui_data(mob/user)
+ var/list/data = list()
+ if(istype(src, /obj/item/folder/syndicate))
+ data["theme"] = "syndicate"
+ data["bg_color"] = "[bg_color]"
+ data["folder_name"] = "[name]"
+
+ data["contents"] = list()
+ data["contents_ref"] = list()
+ for(var/Content in src)
+ data["contents"] += "[Content]"
+ data["contents_ref"] += "[REF(Content)]"
+
+ return data
+
+/obj/item/folder/ui_act(action, params)
+ . = ..()
+ if(.)
+ return
-/obj/item/folder/Topic(href, href_list)
- ..()
if(usr.stat != CONSCIOUS || HAS_TRAIT(usr, TRAIT_HANDS_BLOCKED))
return
- if(usr.contents.Find(src))
-
- if(href_list["remove"])
- var/obj/item/I = locate(href_list["remove"]) in src
- if(istype(I))
- I.forceMove(usr.loc)
- usr.put_in_hands(I)
-
- if(href_list["read"])
- var/obj/item/I = locate(href_list["read"]) in src
- if(istype(I))
- usr.examinate(I)
-
- //Update everything
- attack_self(usr)
- update_appearance()
-
-/obj/item/folder/documents
- name = "folder- 'TOP SECRET'"
- desc = "A folder stamped \"Top Secret - Property of Nanotrasen Corporation. Unauthorized distribution is punishable by death.\""
-
-/obj/item/folder/documents/Initialize()
- . = ..()
- new /obj/item/documents/nanotrasen(src)
- update_appearance()
-
-/obj/item/folder/syndicate
- icon_state = "folder_syndie"
- name = "folder- 'TOP SECRET'"
- desc = "A folder stamped \"Top Secret - Property of The Syndicate.\""
-
-/obj/item/folder/syndicate/red
- icon_state = "folder_sred"
-
-/obj/item/folder/syndicate/red/Initialize()
- . = ..()
- new /obj/item/documents/syndicate/red(src)
- update_appearance()
-
-/obj/item/folder/syndicate/blue
- icon_state = "folder_sblue"
-
-/obj/item/folder/syndicate/blue/Initialize()
- . = ..()
- new /obj/item/documents/syndicate/blue(src)
- update_appearance()
-
-/obj/item/folder/syndicate/mining/Initialize()
- . = ..()
- new /obj/item/documents/syndicate/mining(src)
- update_appearance()
+ switch(action)
+ // Take item out
+ if("remove")
+ var/obj/item/Item = locate(params["ref"]) in src
+ remove_item(Item, usr)
+ . = TRUE
+ // Inspect the item
+ if("examine")
+ var/obj/item/Item = locate(params["ref"]) in src
+ if(istype(Item))
+ usr.examinate(Item)
+ . = TRUE
diff --git a/code/modules/paperwork/folders_premade.dm b/code/modules/paperwork/folders_premade.dm
new file mode 100644
index 00000000000..783b2df201e
--- /dev/null
+++ b/code/modules/paperwork/folders_premade.dm
@@ -0,0 +1,55 @@
+/obj/item/folder/blue
+ desc = "A blue folder."
+ icon_state = "folder_blue"
+ bg_color = "#355e9f"
+
+/obj/item/folder/red
+ desc = "A red folder."
+ icon_state = "folder_red"
+ bg_color = "#b5002e"
+
+/obj/item/folder/yellow
+ desc = "A yellow folder."
+ icon_state = "folder_yellow"
+ bg_color = "#b88f3d"
+
+/obj/item/folder/white
+ desc = "A white folder."
+ icon_state = "folder_white"
+ bg_color = "#d9d9d9"
+
+/obj/item/folder/documents
+ name = "folder- 'TOP SECRET'"
+ desc = "A folder stamped \"Top Secret - Property of Nanotrasen Corporation. Unauthorized distribution is punishable by death.\""
+
+/obj/item/folder/documents/Initialize()
+ . = ..()
+ new /obj/item/documents/nanotrasen(src)
+ update_appearance()
+
+/obj/item/folder/syndicate
+ icon_state = "folder_syndie"
+ bg_color = "#3f3f3f"
+ name = "folder- 'TOP SECRET'"
+ desc = "A folder stamped \"Top Secret - Property of The Syndicate.\""
+
+/obj/item/folder/syndicate/red
+ icon_state = "folder_sred"
+
+/obj/item/folder/syndicate/red/Initialize()
+ . = ..()
+ new /obj/item/documents/syndicate/red(src)
+ update_appearance()
+
+/obj/item/folder/syndicate/blue
+ icon_state = "folder_sblue"
+
+/obj/item/folder/syndicate/blue/Initialize()
+ . = ..()
+ new /obj/item/documents/syndicate/blue(src)
+ update_appearance()
+
+/obj/item/folder/syndicate/mining/Initialize()
+ . = ..()
+ new /obj/item/documents/syndicate/mining(src)
+ update_appearance()
diff --git a/code/modules/paperwork/paper.dm b/code/modules/paperwork/paper.dm
index 39c1c39c7a5..dc44faefb40 100644
--- a/code/modules/paperwork/paper.dm
+++ b/code/modules/paperwork/paper.dm
@@ -198,7 +198,11 @@
SStgui.close_uis(src)
return
- if(istype(P, /obj/item/pen) || istype(P, /obj/item/toy/crayon))
+ // Enable picking paper up by clicking on it with the clipboard or folder
+ if(istype(P, /obj/item/clipboard) || istype(P, /obj/item/folder))
+ P.attackby(src, user)
+ return
+ else if(istype(P, /obj/item/pen) || istype(P, /obj/item/toy/crayon))
if(length(info) >= MAX_PAPER_LENGTH) // Sheet must have less than 1000 charaters
to_chat(user, "This sheet of paper is full!")
return
diff --git a/tgstation.dme b/tgstation.dme
index 4eb9f0caf7e..a1cae218f9f 100644
--- a/tgstation.dme
+++ b/tgstation.dme
@@ -2800,6 +2800,7 @@
#include "code\modules\paperwork\contract.dm"
#include "code\modules\paperwork\filingcabinet.dm"
#include "code\modules\paperwork\folders.dm"
+#include "code\modules\paperwork\folders_premade.dm"
#include "code\modules\paperwork\handlabeler.dm"
#include "code\modules\paperwork\paper.dm"
#include "code\modules\paperwork\paper_cutter.dm"
diff --git a/tgui/packages/tgui/interfaces/Folder.js b/tgui/packages/tgui/interfaces/Folder.js
new file mode 100644
index 00000000000..f4847a1f1b0
--- /dev/null
+++ b/tgui/packages/tgui/interfaces/Folder.js
@@ -0,0 +1,52 @@
+import { useBackend } from "../backend";
+import { Box, Button, Flex, Section } from "../components";
+import { Window } from "../layouts";
+
+export const Folder = (props, context) => {
+ const { act, data } = useBackend(context);
+ const { theme, bg_color, folder_name, contents, contents_ref } = data;
+ return (
+
+
+ {contents.length > 0 ? (
+ <>
+ {contents.map((item, index) => (
+ <>
+
+
+ {item}
+
+
+ {
+
+
+
+ >
+ ))}
+ >
+ ) : (
+
+
+ This folder is empty!
+
+
+ )}
+
+
+ );
+};