Backbone v1 for Backwater games
@@ -0,0 +1 @@
|
||||
node_modules/
|
||||
|
After Width: | Height: | Size: 75 KiB |
|
After Width: | Height: | Size: 1005 KiB |
|
After Width: | Height: | Size: 3.7 KiB |
|
After Width: | Height: | Size: 361 KiB |
|
After Width: | Height: | Size: 4.1 KiB |
|
After Width: | Height: | Size: 3.2 KiB |
|
After Width: | Height: | Size: 1.6 KiB |
|
After Width: | Height: | Size: 321 B |
|
After Width: | Height: | Size: 270 B |
|
After Width: | Height: | Size: 26 KiB |
|
After Width: | Height: | Size: 9.0 KiB |
|
After Width: | Height: | Size: 319 B |
|
After Width: | Height: | Size: 3.4 KiB |
|
After Width: | Height: | Size: 4.3 KiB |
|
After Width: | Height: | Size: 3.1 KiB |
|
After Width: | Height: | Size: 981 KiB |
|
After Width: | Height: | Size: 29 KiB |
|
After Width: | Height: | Size: 32 KiB |
|
After Width: | Height: | Size: 3.1 KiB |
|
After Width: | Height: | Size: 16 KiB |
|
After Width: | Height: | Size: 28 KiB |
|
After Width: | Height: | Size: 5.7 KiB |
|
After Width: | Height: | Size: 8.2 KiB |
|
After Width: | Height: | Size: 544 B |
|
After Width: | Height: | Size: 29 KiB |
|
After Width: | Height: | Size: 3.3 KiB |
|
After Width: | Height: | Size: 1.9 KiB |
|
After Width: | Height: | Size: 1.7 KiB |
|
After Width: | Height: | Size: 4.3 KiB |
|
After Width: | Height: | Size: 3.0 KiB |
|
After Width: | Height: | Size: 43 KiB |
|
After Width: | Height: | Size: 50 KiB |
|
After Width: | Height: | Size: 108 KiB |
|
After Width: | Height: | Size: 50 KiB |
|
After Width: | Height: | Size: 100 KiB |
|
After Width: | Height: | Size: 104 KiB |
|
After Width: | Height: | Size: 99 KiB |
|
After Width: | Height: | Size: 43 KiB |
|
After Width: | Height: | Size: 2.9 KiB |
|
After Width: | Height: | Size: 432 KiB |
|
After Width: | Height: | Size: 522 KiB |
|
After Width: | Height: | Size: 738 KiB |
|
After Width: | Height: | Size: 783 KiB |
|
After Width: | Height: | Size: 3.8 KiB |
|
After Width: | Height: | Size: 1.6 KiB |
|
After Width: | Height: | Size: 36 KiB |
|
After Width: | Height: | Size: 2.8 KiB |
|
After Width: | Height: | Size: 2.6 KiB |
|
After Width: | Height: | Size: 3.2 KiB |
|
After Width: | Height: | Size: 2.0 KiB |
|
After Width: | Height: | Size: 2.5 KiB |
|
After Width: | Height: | Size: 2.0 KiB |
@@ -0,0 +1,3 @@
|
||||
{
|
||||
"presets": ["@babel/preset-env"]
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
{
|
||||
"ext":"pug, js, json, scss",
|
||||
"ignore":["**/javascript/index.js","*.html","**/translation.json"],
|
||||
"verbose":true
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
{
|
||||
"name": "Backbone",
|
||||
"version": "1.0.0",
|
||||
"description": "Below is the information on how the Backbone project will be handled and developed.",
|
||||
"main": "index.js",
|
||||
"scripts": {
|
||||
"start": "nodemon render.js",
|
||||
"test": "jest",
|
||||
"wtest":"jest --watchAll"
|
||||
},
|
||||
"keywords": [],
|
||||
"author": "",
|
||||
"license": "ISC",
|
||||
"devDependencies": {
|
||||
"@babel/preset-env": "^7.16.11",
|
||||
"babel-jest": "^27.5.1",
|
||||
"jest": "^27.2.5",
|
||||
"jest-summary-reporter": "^0.0.2",
|
||||
"jsdom": "^20.0.0",
|
||||
"nodemon": "^2.0.20",
|
||||
"pug": "^3.0.2",
|
||||
"sass-embedded": "^1.55.0",
|
||||
"underscore": "^1.13.6"
|
||||
},
|
||||
"jest": {
|
||||
"transform": {
|
||||
"^.+\\.[t|j]sx?$": "babel-jest"
|
||||
},
|
||||
"reporters": [
|
||||
"default",
|
||||
[
|
||||
"jest-summary-reporter",
|
||||
{
|
||||
"failuresOnly": false
|
||||
}
|
||||
]
|
||||
]
|
||||
}
|
||||
}
|
||||
|
After Width: | Height: | Size: 190 KiB |
@@ -0,0 +1,17 @@
|
||||
const k = require('./source/scaffold');
|
||||
const fs = require('fs/promises');
|
||||
const jsdom = require('jsdom');
|
||||
const { JSDOM } = jsdom;
|
||||
|
||||
const generate = async ()=>{
|
||||
const [pugOut] = await k.all({source:'./source',destination:'./'});
|
||||
const dom = new JSDOM(pugOut);
|
||||
const { window } = dom;
|
||||
const { document } = window;
|
||||
const scriptContent = document.querySelector('script').innerHTML;
|
||||
const scriptPrepend = await fs.readFile('./source/scaffold/scripts/mock20.js','utf8');
|
||||
const scriptAppend = await fs.readFile('./source/scaffold/scripts/mockScaffold.js','utf8');
|
||||
fs.writeFile('./source/javascript/index.js',`${scriptPrepend}\n${scriptContent}\n${scriptAppend}`);
|
||||
}
|
||||
|
||||
generate();
|
||||
@@ -0,0 +1,10 @@
|
||||
{
|
||||
"html": "backbone.html",
|
||||
"css": "backbone.css",
|
||||
"authors": "Scott Casey",
|
||||
"roll20userid": "459831",
|
||||
"preview": "preview.jpg",
|
||||
"instructions": "This is the official sheet for the backbone system by [Backwater games](https://backwater-games.itch.io/).",
|
||||
"legacy": false,
|
||||
"compendium":"backbone"
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
&{template:backbone} {{character_name=John Smith of the overly complex surname}} {{title=Example Action That has some stupidly long name}} {{roll_name=Athletics}} {{roll=[[1d20+5]]}} {{damage=[[1d8+5]]}} {{description=Lorem ipsum dolor sit amet consectetur adipisicing elit. Id iure illum reprehenderit non minus voluptatem magni? Autem consequuntur rerum distinctio harum! Harum eaque culpa **tempore** [[1d100]] delectus unde officia? Doloribus id *deleniti* voluptatum eos? Nam, exercitationem voluptatum. Similique illum dolorum accusantium tenetur. Tenetur repellat consectetur, eum mollitia odit quod veritatis placeat? [Example button](! Does a thing)}}
|
||||
@@ -0,0 +1,7 @@
|
||||
+tab({tabName:'npc',container:'article'})#npc
|
||||
include npc/_header.pug
|
||||
include npc/_basicStats.pug
|
||||
include npc/_skills.pug
|
||||
include npc/_weapons.pug
|
||||
include npc/_abilities.pug
|
||||
include npc/_gear.pug
|
||||
@@ -0,0 +1,12 @@
|
||||
include pc/_active_conditions.pug
|
||||
+tab({tabName:'pc',container:'article'})#pc
|
||||
include pc/_conditions.pug
|
||||
include pc/_header.pug
|
||||
include pc/_basic_stats.pug
|
||||
include pc/_combat_stats.pug
|
||||
include pc/_skills.pug
|
||||
include pc/_gear.pug
|
||||
include pc/_weapons.pug
|
||||
include pc/_archetypes.pug
|
||||
include pc/_traits.pug
|
||||
include pc/_notes.pug
|
||||
@@ -0,0 +1,19 @@
|
||||
+hidden({name:'whisper',value:' '})
|
||||
+tab({tabName:'settings',button:{class:'pictos',content:'y'},container:'article'})#settings
|
||||
h1(data-i18n='settings')
|
||||
+select-label({
|
||||
inputObj:{name:'character type',class:'underlined',trigger:{
|
||||
triggeredFuncs:['sheetTypeDisplay']
|
||||
}},
|
||||
spanObj:{'data-i18n':'character type'},
|
||||
})
|
||||
+option({'data-i18n':'pc',value:'pc',selected:''})
|
||||
+option({'data-i18n':'npc',value:'npc'})
|
||||
+select-label({
|
||||
inputObj:{name:'whisper',class:'underlined',trigger:{
|
||||
triggeredFuncs:['sheetTypeDisplay']
|
||||
}},
|
||||
spanObj:{'data-i18n':'whisper rolls to gm'},
|
||||
})
|
||||
+option({'data-i18n':'never',value:'',selected:''})
|
||||
+option({'data-i18n':'always',value:'/w gm '})
|
||||
@@ -0,0 +1,32 @@
|
||||
section(aria-labelledby='npc-ability-header' id='npc-abilities').npc-abilities.npc-separator.repeating-container
|
||||
h3(data-i18n='abilities')
|
||||
+customControlFieldset({
|
||||
name:'ability'
|
||||
})
|
||||
+collapse
|
||||
.collapsed.inline
|
||||
+roller({
|
||||
name:'roll',
|
||||
trigger:{triggeredFuncs:['rollRepeating']},
|
||||
class:'inline-flex-box half-gap'
|
||||
})
|
||||
+span({name:'type','data-i18n-dynamic':''})
|
||||
+span({name:'name'})
|
||||
+span({name:'description',class:'inline-description'})
|
||||
.expanded
|
||||
.span-all.flex-box.half-gap.flex-wrap
|
||||
+roller({name:'roll',trigger:{
|
||||
triggeredFuncs:['rollRepeating']
|
||||
}})
|
||||
+select({name:'type',class:'underlined'})
|
||||
+option({value:'','data-i18n':'select one'})
|
||||
each value in ['action','blitz','counter','passive']
|
||||
+option({value,'data-i18n':value})
|
||||
+text({name:'name','data-i18n-placeholder':'name',class:'underlined flex-min-content'})
|
||||
+skillSelect
|
||||
.headed-textarea
|
||||
h4(data-i18n='description')
|
||||
+adaptiveTextarea({name:'description',class:'boxed'})
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,25 @@
|
||||
mixin npcCircleAttribute(name,attrName,i18n)
|
||||
.overlay-content
|
||||
div(class=attrName || name).circle.basic-border.ratio1-1
|
||||
+input-label({
|
||||
inputObj:{type:'number',name:attrName || name},
|
||||
spanObj:{'data-i18n':i18n || `${name} abbreviation`,role:'heading','aria-level':3},
|
||||
divObj:{class:`stacked center no-gap overlaid-content`}
|
||||
})
|
||||
|
||||
section#npc-stats.tiny-gap.npc-separator
|
||||
.attributes.flex-box.half-gap.justify-space-around.flex-wrap
|
||||
each name in attributes
|
||||
+attributeHolder(name)
|
||||
.armor-movement.flex-box.half-gap.justify-space-around.flex-wrap
|
||||
each name in ['health','resolve']
|
||||
+npcCircleAttribute(name,`${name} max`,name)
|
||||
each obj in [...movementArmor,{name:'adrenaline'}]
|
||||
+npcCircleAttribute(obj.name)
|
||||
.characteristics.half-gap.justify-space-between
|
||||
each obj,name in characteristics
|
||||
+input-label({
|
||||
inputObj:{name,type:'number',class:'underlined'},
|
||||
spanObj:{'data-i18n':`${name}-abbreviation`,role:'heading','aria-level':3},
|
||||
divObj:{class:'no-gap'}
|
||||
})
|
||||
@@ -0,0 +1,3 @@
|
||||
section(aria-labelledby='npc-gear-header' id='npc-gear').npc-gear
|
||||
h3(data-i18n='items')
|
||||
+adaptiveTextarea({name:'npc items',class:'boxed'})
|
||||
@@ -0,0 +1,10 @@
|
||||
section#npc-header.half-gap.align-items-end
|
||||
+text({name:'character name',value:'',role:'heading','aria-level':2,class:'underlined'})
|
||||
+dual-input-label({
|
||||
inputArr:[
|
||||
{type:'number',name:'difficulty size',class:'underlined'},
|
||||
{type:'number',name:'difficulty level',class:'underlined'}
|
||||
],
|
||||
spanObj:{'data-i18n':'difficulty level abbreviation',class:'uppercase'},
|
||||
separator:'-'
|
||||
})
|
||||
@@ -0,0 +1,34 @@
|
||||
-
|
||||
const skillRefs = {
|
||||
skill: {i18n: 'skills', collection:basicSkills},
|
||||
specialty: {i18n: 'specialty skills'},
|
||||
combat: {i18n: 'combat skills', collection:combatSkills}
|
||||
};
|
||||
mixin npcSkillContainer(skill)
|
||||
div(class=`npc-${skill.replace(/\s+/g,'-').replace(/\(|\)|\//g,'')}-container`).input-label.collapse-container.avoid-break
|
||||
+roller({
|
||||
name:skill,
|
||||
role:'heading',
|
||||
'aria-level':3,
|
||||
'data-i18n':skill
|
||||
})
|
||||
+plusControl({
|
||||
name:skill,
|
||||
classAdd:'collapsed',
|
||||
defaultValue:''
|
||||
})
|
||||
+number({
|
||||
name:skill,
|
||||
class:'expanded underlined',
|
||||
trigger:{
|
||||
triggeredFuncs:['displayNPCSkill']
|
||||
}
|
||||
})
|
||||
//- End mixin
|
||||
.collapse-container
|
||||
+collapse('npc skills')
|
||||
each name in ['skill','combat']
|
||||
section(aria-labelledby=`npc-${name}-header` id=`npc-${name}`).collapse-container.npc-skill-container
|
||||
h3(data-i18n=skillRefs[name].i18n id=`npc-${name}-header`)
|
||||
each obj in skillRefs[name].collection
|
||||
+npcSkillContainer(obj.name)
|
||||
@@ -0,0 +1,28 @@
|
||||
section(aria-labelledby='npc-weapon-header' id='npc-weapons').npc-weapons.npc-separator.repeating-container
|
||||
h3(data-i18n='attacks')
|
||||
+customControlFieldset({
|
||||
name:'weapon'
|
||||
})
|
||||
+collapse
|
||||
.collapsed.flex-box.flex-wrap.half-gap
|
||||
+roller({
|
||||
name:'roll',
|
||||
trigger:{triggeredFuncs:['rollRepeating']},
|
||||
class:'flex-box half-gap'
|
||||
})
|
||||
+span({name:'skill','data-i18n-dynamic':''})
|
||||
+span({name:'name'})
|
||||
+hidden({name:'damage',value:'',class:'empty-hider'})
|
||||
.flex-box.tiny-gap
|
||||
+span({name:'damage'})
|
||||
span(data-i18n='damage-abbreviation')
|
||||
+hidden({name:'range',value:'',class:'empty-hider'})
|
||||
.flex-box.tiny-gap
|
||||
span(data-i18n='range')
|
||||
+span({name:'range'})
|
||||
.expanded
|
||||
+weaponDetails(true)
|
||||
+sizeAndSlot
|
||||
+adaptiveTextarea({name:'description',class:'boxed'}).description
|
||||
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
ul(data-container-tab="backbone" data-tab="pc").tabs__container.flex-box.flex-wrap.justify-center.condition-summary.half-gap
|
||||
each condition in conditions
|
||||
+checkbox({name:condition,value:1,hidden:'',class:'display-control',trigger:{
|
||||
triggeredFuncs:['resetCondition']
|
||||
}})
|
||||
li(class=`condition-item--${condition}`).condition-item.flex-box.tiny-gap
|
||||
+conditionCheck(condition)
|
||||
+inputWithControls({name:`track ${condition}`,type:'number',class:'underlined'})
|
||||
@@ -0,0 +1,15 @@
|
||||
section#archetype.repeating-container
|
||||
h2(data-i18n='abilities').header
|
||||
+customControlFieldset({
|
||||
name:'ability'
|
||||
})
|
||||
+collapse
|
||||
.span-all.flex-box.half-gap.flex-wrap
|
||||
+roller({name:'roll',trigger:{
|
||||
triggeredFuncs:['rollRepeating']
|
||||
}})
|
||||
+text({name:'name','data-i18n-placeholder':'name',class:'underlined flex-min-content'})
|
||||
+skillSelect
|
||||
.headed-textarea.expanded
|
||||
h4(data-i18n='description')
|
||||
+adaptiveTextarea({name:'description',class:'boxed'})
|
||||
@@ -0,0 +1,64 @@
|
||||
section(data-i18n-aria-label="basic stats")#basic-stats
|
||||
.characteristics
|
||||
h2(data-i18n='characteristics')
|
||||
-
|
||||
const groupHolder = Object.values(characteristics).reduce((acc,obj)=>{
|
||||
const endIndex = Math.max(acc.length - 1,0)
|
||||
if(!acc[endIndex] || acc[endIndex][1]){
|
||||
const dest = [];
|
||||
dest.push(obj);
|
||||
acc.push(dest);
|
||||
}else{
|
||||
acc[endIndex].push(obj);
|
||||
}
|
||||
return acc;
|
||||
},[]);
|
||||
each arr in groupHolder
|
||||
.even-flow
|
||||
each obj in arr
|
||||
- const trigger = {affects:obj.affects};
|
||||
+statContainer({class:obj.name})
|
||||
+input-label({
|
||||
inputObj:{name:obj.name,type:'number',trigger},
|
||||
spanObj:{'data-i18n':`${obj.name}-abbreviation`,role:'heading','aria-level':3},
|
||||
divObj:{class:'stacked center no-gap'}
|
||||
})
|
||||
.attributes
|
||||
h2(data-i18n='attributes')
|
||||
-
|
||||
const attrHolder = attributes.reduce((acc,name) => {
|
||||
const endIndex = Math.max(acc.length - 1,0)
|
||||
if(!acc[endIndex] || acc[endIndex][1]){
|
||||
const dest = [];
|
||||
dest.push(name);
|
||||
acc.push(dest);
|
||||
}else{
|
||||
acc[endIndex].push(name);
|
||||
}
|
||||
return acc;
|
||||
},[]);
|
||||
each arr in attrHolder
|
||||
.even-flow
|
||||
each name in arr
|
||||
+attributeHolder(name)
|
||||
.armor-movement.collapse-container
|
||||
+collapse('armor-collapse')(checked)
|
||||
h2(data-i18n='armor-movement')
|
||||
each obj in movementArmor
|
||||
+statContainer({class:obj.name.replace(/\s.+/,'')}).circle
|
||||
+input-label({
|
||||
inputObj:{type:'number',...obj},
|
||||
spanObj:{'data-i18n':`${obj.name} abbreviation`,role:'heading','aria-level':3},
|
||||
divObj:{class:`stacked center no-gap`}
|
||||
})
|
||||
.headed-textarea.armor-details.collapse-container.tiny-gap
|
||||
.flex-box.half-gap(style="width:100%")
|
||||
+text({name:'armor name',value:'','data-i18n-placeholder':'equipped armor',class:'flex-min-content underlined'})
|
||||
+action({
|
||||
name:'unequip armor',
|
||||
'data-i18n':'unequip',
|
||||
class:'control-button',
|
||||
trigger:{triggeredFuncs:['equipArmor']}
|
||||
})
|
||||
+adaptiveTextarea({name:'armor details',class:'boxed underlined--light'}).expanded
|
||||
|
||||
@@ -0,0 +1,32 @@
|
||||
section(data-i18n-aria-label="combat stats")#combat-stats
|
||||
each name in ['health','resolve']
|
||||
.health-container
|
||||
+statContainer({class:name})
|
||||
+roller-label({
|
||||
inputObj:{name:name,type:'number'},
|
||||
buttonObj:{name,'data-i18n':name,role:'heading','aria-level':3,trigger:{
|
||||
triggeredFuncs:['rollHealthCheck']
|
||||
}},
|
||||
divObj:{class:'stacked center'}
|
||||
})
|
||||
+statContainer({class:`${name} max`})
|
||||
+input-label({
|
||||
inputObj:{name:`${name} max`,type:'number'},
|
||||
spanObj:{'data-i18n':'maximum',role:'heading','aria-level':3},
|
||||
divObj:{class:'stacked'}
|
||||
})
|
||||
.luck-container
|
||||
h3(data-i18n='luck')
|
||||
each value in ['odd','even']
|
||||
+input-label({
|
||||
inputObj:{name:'luck',type:'radio',value},
|
||||
spanObj:{'data-i18n':value}
|
||||
})
|
||||
+roller({name:'luck',role:'heading','aria-level':3,trigger:{triggeredFuncs:['rollLuck']}})
|
||||
.adrenaline-container.input-label
|
||||
label(for='adrenaline')
|
||||
h3(data-i18n='adrenaline')
|
||||
.parens-holder.adrenaline
|
||||
span.parentheses.large-parentheses (
|
||||
+inputWithControls({name:'adrenaline',id:'adrenaline',type:'number'})
|
||||
span.parentheses.large-parentheses )
|
||||
@@ -0,0 +1,10 @@
|
||||
aside#pc-conditions.pc-conditions.sidebar.sidebar--left.conditions-sidebar.fresh
|
||||
+action({
|
||||
name:'condition display',
|
||||
class:'sidebar-toggle sidebar--right fresh',
|
||||
trigger:{triggeredFuncs:['showConditions']}
|
||||
})
|
||||
h4(data-i18n="conditions")
|
||||
.flex-box.flex-wrap.justify-center
|
||||
each condition in conditions
|
||||
+conditionCheck(condition)
|
||||
@@ -0,0 +1,66 @@
|
||||
section#gear.tall-2
|
||||
.coin
|
||||
h2(data-i18n='coin & assets')
|
||||
each name in ['credit','coin']
|
||||
+input-label({
|
||||
inputObj:{name,type:'number',class:'underlined'},
|
||||
spanObj:{'data-i18n':name},
|
||||
})
|
||||
+input-label({
|
||||
inputObj:{name:'badge',type:'text',class:'underlined'},
|
||||
spanObj:{'data-i18n':'badge'},
|
||||
})
|
||||
.input-label
|
||||
span(data-i18n='clothes').input-label__text
|
||||
+adaptiveInput({name:'clothes',class:'underlined'}).input-label__input
|
||||
.repeating-container.equipped
|
||||
.flex.header.center
|
||||
h2(data-i18n='equipped gear')
|
||||
+checkbox({name:'overburdened',value:1,hidden:'',class:'over-equip-control',trigger:{
|
||||
calculation:'calcOverburdened'
|
||||
}})
|
||||
+dual-input-label({
|
||||
inputArr:[
|
||||
{name:'item slots',type:'number',readonly:'',class:'underlined',trigger:{affects:['overburdened'],calculation:'calcUsedSlots'}},
|
||||
{name:'item slots max',type:'number',class:'underlined',trigger:{affects:['overburdened'],calculation:'calcItemSlotsMax'}}
|
||||
],
|
||||
spanObj:{'data-i18n':'item slots'}
|
||||
})
|
||||
+customControlFieldset({
|
||||
name:'equipped'
|
||||
})
|
||||
+collapse
|
||||
.flex-box.half-gap.span-all.align-items-center
|
||||
+checkbox({name:'equipped',value:1,checked:'',trigger:{triggeredFuncs:['equipItem'],affects:['item slots']}})
|
||||
+text({name:'name',class:'underlined flex-min-content'})
|
||||
+dual-input-label({
|
||||
inputArr:[{name:'uses',type:'number',class:'underlined'},{name:'uses max',type:'number',class:'underlined expanded'}],
|
||||
spanObj:{'data-i18n':'uses'},
|
||||
divObj:{class:'collapse-container'},
|
||||
separatorObj:{content:'/',class:'expanded'}
|
||||
})
|
||||
+roller({name:'roll',trigger:{
|
||||
triggeredFuncs:['rollRepeating']
|
||||
}})
|
||||
+skillSelect.expanded.skill
|
||||
+sizeAndSlot
|
||||
+adaptiveTextarea({name:'description',class:'boxed'}).description.expanded
|
||||
.repeating-container.stored
|
||||
h2(data-i18n='stored gear').header
|
||||
+customControlFieldset({
|
||||
name:'stored'
|
||||
})
|
||||
+weaponDetails
|
||||
+sectionControl({name:'type',value:'gear'}).expanded.gear
|
||||
+dual-input-label({
|
||||
inputArr:[{name:'uses',type:'number',class:'underlined'},{name:'uses max',type:'number',class:'underlined'}],
|
||||
spanObj:{'data-i18n':'uses'}
|
||||
})
|
||||
+skillSelect.expanded.skill
|
||||
+sectionControl({name:'type',value:'armor'}).expanded.gear
|
||||
+input-label({
|
||||
inputObj:{name:'armor bonus',type:'number',class:'underlined'},
|
||||
spanObj:{'data-i18n':'armor bonus'}
|
||||
})
|
||||
+sizeAndSlot
|
||||
+adaptiveTextarea({name:'description',class:'boxed'}).description.expanded
|
||||
@@ -0,0 +1,16 @@
|
||||
section#character-info.span-all
|
||||
div
|
||||
each name,i in ['character name','age','gender']
|
||||
- inputObj = {name,class:'underlined',type:'text'};
|
||||
if i > 0
|
||||
- inputObj.class += ' text-center';
|
||||
+input-label({
|
||||
inputObj,
|
||||
spanObj:{'data-i18n':name.replace(/character /,''),role:'heading','aria-level':2}
|
||||
})
|
||||
div
|
||||
each obj in [{name:'origin',type:'text'},{name:'dialect',type:'text'},{name:'level',type:'number'},{name:'archetype',type:'text'},{name:'ideals',type:'text'},{name:'fortune',type:'text'}]
|
||||
+input-label({
|
||||
inputObj:{name:obj.name,class:'underlined',type:obj.type},
|
||||
spanObj:{'data-i18n':obj.name,role:'heading','aria-level':2}
|
||||
})
|
||||
@@ -0,0 +1,5 @@
|
||||
each name in ['backstory','notes']
|
||||
section(id=name)
|
||||
.headed-textarea
|
||||
h2(data-i18n=name)
|
||||
+adaptiveTextarea({name:name,class:'boxed'})
|
||||
@@ -0,0 +1,33 @@
|
||||
section(aria-label="skills")#skills.tall-2
|
||||
.basic-skills
|
||||
div
|
||||
h2(data-i18n='basic-skills' style='column-span:all;')#basic-skills
|
||||
.input-label
|
||||
span(data-i18n='skill points').input-label__text
|
||||
+inputWithControls({name:'skill points',type:'number',class:'underlined'})
|
||||
.skill-container
|
||||
+skillRows(basicSkills)
|
||||
.combat-skills
|
||||
h2(data-i18n="combat skills")
|
||||
+skillRows(combatSkills)
|
||||
.specialty-skills.repeating-container
|
||||
h2(data-i18n="specialty skills").header
|
||||
+customControlFieldset({
|
||||
name:'specialty',
|
||||
})
|
||||
+roller({name:'roll',role:'heading','aria-level':3,class:'dicefontd20',trigger:{
|
||||
triggeredFuncs:['rollSkill']
|
||||
}})
|
||||
+text({name:'name',class:'underlined skill-name'})
|
||||
+fillLeft({
|
||||
radioObj:{name:`proficiency`,value:-1},
|
||||
divObj:{class:'proficiency'},
|
||||
valueArray:[-1,0,1,2,3,4],
|
||||
noClear:true,
|
||||
displayValues:['-1','+0','+1','+2','+3','+4']
|
||||
})
|
||||
+select({name:'characteristic'})
|
||||
+option({value:'','data-i18n':'select',selected:''})
|
||||
each obj,value in characteristics
|
||||
+option({value,'data-i18n':`${value} abbreviation`})
|
||||
+checkbox({name:`${name} mastery`,value:1,class:'mastery'})
|
||||
@@ -0,0 +1,16 @@
|
||||
section#favorable-traits.repeating-container
|
||||
h3(data-i18n='favorable traits').header
|
||||
+customControlFieldset({
|
||||
name:'favorable'
|
||||
})
|
||||
+collapse
|
||||
+text({name:'name',class:'underlined'})
|
||||
+adaptiveTextarea({name:'description',class:'boxed'}).expanded
|
||||
section#unfavorable-traits.repeating-container
|
||||
h3(data-i18n='unfavorable traits').header
|
||||
+customControlFieldset({
|
||||
name:'unfavorable'
|
||||
})
|
||||
+collapse
|
||||
+text({name:'name',class:'underlined'})
|
||||
+adaptiveTextarea({name:'description',class:'boxed'}).expanded
|
||||
@@ -0,0 +1,24 @@
|
||||
section#weapons.repeating-container
|
||||
h2(data-i18n='equipped weapons').header
|
||||
+customControlFieldset({
|
||||
name:'weapon',
|
||||
trigger:{
|
||||
addFuncs:['addWeapon']
|
||||
}
|
||||
})
|
||||
+weaponDetails(true)
|
||||
+sizeAndSlot
|
||||
+adaptiveTextarea({name:'description',class:'boxed'}).description.expanded
|
||||
.flex-box.gap.flex-wrap.justify-center
|
||||
- let ammoCount = 1;
|
||||
each i in [1,2]
|
||||
.ammo-container.flex-box.half-gap.align-items-center
|
||||
+text({name:`container ${i}`,type:'text',class:'underlined container-name','data-i18n-placeholder':'ammo container'})
|
||||
each n in [1,2]
|
||||
.parens-holder
|
||||
span.parentheses.large-parentheses (
|
||||
.flex-box.stacked.center
|
||||
+number({name:`ammo ${ammoCount}`,class:'underlined'})
|
||||
+text({name:`ammo type ${ammoCount}`,'data-i18n-placeholder':'type',class:'ammo-type'})
|
||||
- ammoCount++;
|
||||
span.parentheses.large-parentheses )
|
||||
@@ -0,0 +1,211 @@
|
||||
//This file will store all of our generic styling for the sheet. Styling for specific sections will be done in individual scss files to make the code easier to read.
|
||||
@use 'mixinsandplaceholders';
|
||||
@use 'systemVariables';
|
||||
@use 'placeholders/systemPlaceholders';
|
||||
@import url('https://fonts.googleapis.com/css?family=IM+Fell+English+SC|Trade+Winds|Material+Icons&display=swap');
|
||||
|
||||
html{
|
||||
font-size:16px;
|
||||
}
|
||||
.ui-dialog{
|
||||
@extend %systemVariables;
|
||||
.tab-content .charsheet{
|
||||
.repitem{
|
||||
.roller:nth-last-child(3){
|
||||
padding-right:var(--half-gap);
|
||||
}
|
||||
}
|
||||
.large-parentheses {
|
||||
align-items: center;
|
||||
font-size: 2rem;
|
||||
}
|
||||
.fill-left__radio[data-value]:checked:before{
|
||||
font-family:var(--contentFont);
|
||||
}
|
||||
.parentheses{
|
||||
font-family:var(--topHeaderFont);
|
||||
}
|
||||
.text-center{
|
||||
text-align: center;
|
||||
}
|
||||
.input-controls{
|
||||
display:grid;
|
||||
grid-template-columns: [input-start increment-start] auto [increment-end] 1fr [decrement-start] auto [input-end decrement-end];
|
||||
grid-template-rows: [increment-start input-start decrement-start] auto [increment-end input-end decrement-end];
|
||||
> input{
|
||||
grid-area:input;
|
||||
}
|
||||
}
|
||||
.input-control--button{
|
||||
font-family:var(--topHeaderFont);
|
||||
z-index:100;
|
||||
&:first-of-type{
|
||||
grid-area:increment;
|
||||
}
|
||||
&:last-of-type{
|
||||
grid-area:decrement;
|
||||
}
|
||||
}
|
||||
.even-flow{
|
||||
gap:inherit;
|
||||
display:flex;
|
||||
}
|
||||
/*
|
||||
First of all we apply our default styles.
|
||||
Note that because we are using the placeholder, these styles would be first up in the cascade even if we put the extend declaration last.
|
||||
This is done first so that when we read the code, we can easily see that it is applied, and anything after it will overwrite those default styles.
|
||||
*/
|
||||
|
||||
// Clears the default Roll20 styling from all elements so that we can style them as we want more easily. We are using 3 classes here because we have to use at least that level of specificity to overcome many of the default Roll20 styles.
|
||||
@extend %defaultStyles;
|
||||
padding-top:0;
|
||||
.roller{
|
||||
&:not([role]){
|
||||
@extend %h4;
|
||||
}
|
||||
display:flex;
|
||||
gap:var(--half-gap);
|
||||
align-items:center;
|
||||
&:before{
|
||||
font-family:dicefontd20;
|
||||
content:'T'
|
||||
}
|
||||
}
|
||||
button{
|
||||
color:var(--fontColor);
|
||||
cursor:pointer;
|
||||
}
|
||||
h3{
|
||||
grid-area:header;
|
||||
}
|
||||
|
||||
.styled-button{
|
||||
@extend %sectionBoxShadow;
|
||||
background-color: var(--backColor);
|
||||
border: 0;
|
||||
border-radius: .5rem;
|
||||
box-sizing: border-box;
|
||||
cursor:pointer;
|
||||
transition: {
|
||||
property:background-color,color;
|
||||
duration:var(--revealTime);
|
||||
};
|
||||
padding-inline:var(--half-gap);
|
||||
text-align:center;
|
||||
|
||||
&:hover {
|
||||
background-color: var(--selectedColor);
|
||||
&,
|
||||
& *{
|
||||
color:var(--dark-secondarytext);
|
||||
}
|
||||
}
|
||||
|
||||
&:focus {
|
||||
outline: 2px solid transparent;
|
||||
outline-offset: 2px;
|
||||
}
|
||||
|
||||
&:focus-visible {
|
||||
box-shadow: none;
|
||||
}
|
||||
}
|
||||
.styled-button--controlled,
|
||||
.styled-button--controlled *{
|
||||
@extend %h4;
|
||||
}
|
||||
.styled-button-control:is(:checked,[type='hidden']:not([value='']):not([value='0'])) + .styled-button--controlled{
|
||||
background-color:var(--selectedColor);
|
||||
&,
|
||||
& *{
|
||||
color:var(--dark-secondarytext);
|
||||
}
|
||||
}
|
||||
.parens-holder{
|
||||
display:flex;
|
||||
align-items:center;
|
||||
> .input-label{
|
||||
gap:0;
|
||||
span{
|
||||
font-size:.8rem;
|
||||
}
|
||||
}
|
||||
}
|
||||
.stat-container{
|
||||
--shadowSize: 1px;
|
||||
border:2px solid var(--fontColor);
|
||||
display:flex;
|
||||
flex-direction:column;
|
||||
align-items:center;
|
||||
break-inside:avoid;
|
||||
aspect-ratio: 1 / 1;
|
||||
justify-content: center;
|
||||
&:not(.circle){
|
||||
border-radius:20px;
|
||||
}
|
||||
}
|
||||
:is(.stat-container,.overlay-content){
|
||||
.input-label__text,
|
||||
.roller{
|
||||
text-shadow:
|
||||
var(--shadowSize) 0 var(--backColor),
|
||||
calc( var(--shadowSize) * -1 ) 0 var(--backColor),
|
||||
0px var(--shadowSize) var(--backColor),
|
||||
0px calc( var(--shadowSize) * -1 ) var(--backColor);
|
||||
}
|
||||
}
|
||||
.circle{
|
||||
@extend %circle;
|
||||
}
|
||||
.overlay-content{
|
||||
display:grid;
|
||||
grid-template-areas:content;
|
||||
place-items:center;
|
||||
> * {
|
||||
grid-area:content !important;
|
||||
}
|
||||
> .overlaid-content{
|
||||
z-index: 100;
|
||||
}
|
||||
}
|
||||
.basic-border{
|
||||
border: 2px solid var(--fontColor);
|
||||
}
|
||||
.avoid-break{
|
||||
break-inside: avoid;
|
||||
}
|
||||
article{
|
||||
position:relative;
|
||||
}
|
||||
.text-check{
|
||||
span{
|
||||
transition: {
|
||||
duration:var(--revealTime);
|
||||
property:color,background-color;
|
||||
};
|
||||
}
|
||||
> input:checked{
|
||||
+ span{
|
||||
background-color:var(--selectedColor);
|
||||
color:var(--backColor);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
.ui-dialog .sheetform{
|
||||
background-color:var(--backColor);
|
||||
transition: {
|
||||
property:background-color;
|
||||
duration:var(--revealTime);
|
||||
};
|
||||
}
|
||||
.sheet-darkmode .ui-dialog{
|
||||
@extend %darkmodeStyle;
|
||||
--imgInvert:invert(0.9);
|
||||
}
|
||||
//the declarations for styles specifically applying to our main element.
|
||||
#main{
|
||||
display:grid;
|
||||
grid-area:content;
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
//- This file will store all mixins and placeholders that have generic use
|
||||
@use 'placeholders/materialIcons';
|
||||
|
||||
@use 'placeholders/pictos';
|
||||
|
||||
@use 'placeholders/hidden';
|
||||
|
||||
@use 'placeholders/textLevel';
|
||||
@use 'placeholders/button';
|
||||
@use 'placeholders/inputBase';
|
||||
@use 'placeholders/inputlabel';
|
||||
@use 'placeholders/collapse';
|
||||
@use 'placeholders/adaptiveInputs';
|
||||
@use 'placeholders/headedText';
|
||||
|
||||
@use 'placeholders/borderPlaceholders';
|
||||
@use 'placeholders/fieldsetStyling';
|
||||
@use 'placeholders/sizingAndRatio';
|
||||
@use 'placeholders/fillLeft';
|
||||
@use 'placeholders/layout';
|
||||
//- Default styles. This Placeholder gets a little complicated. We're going to define several CSS variables in the first lines that will allow us to easily use the same layout principles across the sheet. Additionally, this placeholder is going to apply several styles to various elements. The reason we do this as a placeholder instead of directly in a class' CSS declaration is so that we can easily apply the same styling to our sheet as a whole and to the rolltemplate (note that many of these class specifications have versions prefixed and unprefixed with `.sheet-`
|
||||
%defaultStyles{
|
||||
@extend %textElements;
|
||||
@extend %materialIcons;
|
||||
@extend %hideBase;
|
||||
@extend %textStyles;
|
||||
@extend %headerElements;
|
||||
@extend %inputBase;
|
||||
@extend %button;
|
||||
@extend %r20FontClasses;
|
||||
@extend %input-label;
|
||||
@extend %headed-textarea;
|
||||
@extend %borderStyles;
|
||||
@extend %adaptiveText;
|
||||
@extend %sizesAndRatios;
|
||||
@extend %collapsible;
|
||||
@extend %fieldsetStyling;
|
||||
@extend %fillLeft;
|
||||
@extend %layout;
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
.ui-dialog .tab-content .charsheet {
|
||||
select,
|
||||
textarea,
|
||||
input,
|
||||
.uneditable-input,
|
||||
label,
|
||||
button {
|
||||
all: initial;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,161 @@
|
||||
@use 'mixinsandplaceholders';
|
||||
@use 'systemVariables';
|
||||
@use 'placeholders/systemPlaceholders';
|
||||
|
||||
.sheet-rolltemplate-backbone{
|
||||
@extend %systemVariables;
|
||||
@extend %defaultStyles;
|
||||
--backColor:#FCF5E5;
|
||||
--borderImgRadiusFit:20px;
|
||||
margin-right:-16px;
|
||||
margin-left:-45px;
|
||||
margin-bottom:-7px;
|
||||
padding:var(--grid-gap);
|
||||
&:not(:first-child){
|
||||
margin-top:var(--grid-gap);
|
||||
}
|
||||
|
||||
.sheet-image-border{
|
||||
position: absolute;
|
||||
inset: 0;
|
||||
border: var(--maskSize) solid;
|
||||
border-image-source: var(--borderImageSource);
|
||||
border-image-slice: var(--borderImageSlice);
|
||||
border-image-width: var(--maskSize);
|
||||
border-image-repeat: round;
|
||||
pointer-events: none;
|
||||
z-index:-1;
|
||||
}
|
||||
.sheet-template{
|
||||
position:relative;
|
||||
padding:4px;
|
||||
isolation:isolate;
|
||||
filter: drop-shadow(var(--shadowSize) 0 var(--shadowBlur) var(--shadowColor)) drop-shadow(calc(var(--shadowSize) * -1) 0 var(--shadowBlur) var(--shadowColor)) drop-shadow(0 var(--shadowSize) var(--shadowBlur) var(--shadowColor)) drop-shadow(0 calc(var(--shadowSize) * -1) var(--shadowBlur) var(--shadowColor)) drop-shadow(var(--shadowSize) 0 calc(var(--shadowBlur) * 1.5 ) var(--shadowColor2)) drop-shadow(calc(var(--shadowSize) * -1) 0 calc(var(--shadowBlur) * 1.5 ) var(--shadowColor2)) drop-shadow(0 var(--shadowSize) calc(var(--shadowBlur) * 1.5 ) var(--shadowColor2)) drop-shadow(0 calc(var(--shadowSize) * -1) calc(var(--shadowBlur) * 1.5 ) var(--shadowColor2));
|
||||
> :nth-child(2){
|
||||
border-top-left-radius: var(--borderImgRadiusFit);
|
||||
border-top-right-radius: var(--borderImgRadiusFit);
|
||||
}
|
||||
> :last-child{
|
||||
border-bottom-left-radius: var(--borderImgRadiusFit);
|
||||
border-bottom-right-radius: var(--borderImgRadiusFit);
|
||||
}
|
||||
p,span{
|
||||
font-size:1.3rem;
|
||||
}
|
||||
p{
|
||||
overflow-y:auto;
|
||||
max-height:30rem;
|
||||
margin:0;
|
||||
}
|
||||
a{
|
||||
background-color:transparent;
|
||||
border:none;
|
||||
padding:0;
|
||||
color:var(--fontColor);
|
||||
font-weight:700;
|
||||
&[href^='!'],
|
||||
&[href^='~']{
|
||||
display:inline-grid;
|
||||
grid-template-columns:10px auto;
|
||||
grid-template-areas: 'icon text';
|
||||
&:before{
|
||||
content:'';
|
||||
background:{
|
||||
image: url('https://s3.amazonaws.com/files.d20.io/images/305391097/UIK_ZAJSwqtkuDg5I2g_LQ/original.png?16636241805');
|
||||
repeat:no-repeat;
|
||||
size:contain;
|
||||
position:center;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@mixin pureResult{
|
||||
position:relative;
|
||||
display:flex;
|
||||
align-items:center;
|
||||
&:before{
|
||||
position:absolute;
|
||||
left:-24px;
|
||||
}
|
||||
}
|
||||
@mixin pureSuccess{
|
||||
&:before{
|
||||
content:'';
|
||||
display:block;
|
||||
background-image:var(--successCircle);
|
||||
background-repeat:no-repeat;
|
||||
background-size:contain;
|
||||
width: 24px;
|
||||
height:24px;
|
||||
}
|
||||
}
|
||||
@mixin pureFail{
|
||||
&:before{
|
||||
content:'';
|
||||
display:block;
|
||||
background-image:var(--failCircle);
|
||||
background-repeat:no-repeat;
|
||||
background-size:contain;
|
||||
width: 24px;
|
||||
height:24px;
|
||||
}
|
||||
}
|
||||
.sheet-content{
|
||||
padding: var(--big-gap);
|
||||
.inlinerollresult{
|
||||
@extend %h3-style;
|
||||
background-color: transparent;
|
||||
border:0px solid transparent;
|
||||
font-weight:700;
|
||||
&.fullcrit{
|
||||
color:green;
|
||||
}
|
||||
&.fullfail{
|
||||
color:red;
|
||||
}
|
||||
&.importantroll{
|
||||
color:blue;
|
||||
}
|
||||
}
|
||||
.sheet-pure-success{
|
||||
+ .inlinerollresult{
|
||||
color:var(--fontColor) !important;
|
||||
@include pureResult;
|
||||
&.fullcrit{
|
||||
color:var(--fontColor);
|
||||
@include pureSuccess
|
||||
}
|
||||
&.fullfail{
|
||||
color:var(--fontColor);
|
||||
@include pureFail;
|
||||
}
|
||||
}
|
||||
}
|
||||
.sheet-result .inlinerollresult{
|
||||
@extend %h1;
|
||||
font-size:3rem;
|
||||
}
|
||||
.sheet-result--no-crit{
|
||||
.inlinerollresult{
|
||||
color:var(--fontColor);
|
||||
}
|
||||
}
|
||||
.sheet-result--is-fumble{
|
||||
.inlinerollresult{
|
||||
@include pureResult;
|
||||
@include pureFail;
|
||||
}
|
||||
}
|
||||
.sheet-result--is-crit{
|
||||
.inlinerollresult{
|
||||
@include pureResult;
|
||||
@include pureSuccess;
|
||||
}
|
||||
}
|
||||
}
|
||||
.sheet-description{
|
||||
width:100%;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
@use 'placeholders/defaultVariables';
|
||||
@use 'placeholders/darkmode';
|
||||
%systemVariables{
|
||||
@extend %universalVariables;
|
||||
// Color component variables
|
||||
--errorColor:red;
|
||||
|
||||
// Images
|
||||
--failCircle: url('https://s3.amazonaws.com/files.d20.io/images/318562209/I3x7bfc3_M_QcFnt8tV85Q/original.png?16710625345');
|
||||
--successCircle: url('https://s3.amazonaws.com/files.d20.io/images/318562210/oX_VbZJwiNoujxFnSVumpA/original.png?16710625345');
|
||||
--conditionIcon: url('https://s3.amazonaws.com/files.d20.io/images/318557936/fEiMDUb_UctEstYyXkKlEA/original.png?16710607145');
|
||||
--heart:url('https://s3.amazonaws.com/files.d20.io/images/303476002/EGcfkMfeF7mIRowjCyVy-w/original.png?16625716925');
|
||||
--boot:url('https://s3.amazonaws.com/files.d20.io/images/303476005/Ap6DSJSqAVUkpkEwmKazPA/original.png?16625716925');
|
||||
--bolt:url('https://s3.amazonaws.com/files.d20.io/images/303476003/7La7gESx4Th7OYnkHc4u2Q/original.png?16625716925');
|
||||
--flame:url('https://s3.amazonaws.com/files.d20.io/images/303476004/9l3GwDqA2PNTAULgIvC8EA/original.png?16625716915');
|
||||
--armor:url('https://s3.amazonaws.com/files.d20.io/images/303476001/9BHZGaCcM8H3wbj2W23zdw/original.png?16625716925');
|
||||
--skull: url('https://s3.amazonaws.com/files.d20.io/images/303477021/Vm1A4GWATnboxP65WqEW0A/original.png?16625722085');
|
||||
--borderImageSource: url(https://s3.amazonaws.com/files.d20.io/images/312349470/ovngRYPae8cWAT9W489wJw/original.png?166741640555);
|
||||
--borderImageSlice: 175 fill;
|
||||
|
||||
--maskSize: 20px;
|
||||
--shadowSize: 0px;
|
||||
--shadowBlur: 4px;
|
||||
--shadowColor: rgb(0 0 0 / 0.2);
|
||||
--shadowColor2: rgb(0 0 0 / 0.1);
|
||||
|
||||
// Fonts
|
||||
--topHeaderFont: 'Trade Winds', cursive;
|
||||
--midHeaderFont: 'IM Fell English SC';
|
||||
--contentFont: 'IM Fell English SC';
|
||||
|
||||
--radioSize:15px;
|
||||
--columnSize:370px;
|
||||
|
||||
--imgInvert: invert(0);
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
@use '_borderPlaceholders.scss';
|
||||
%adaptiveText{
|
||||
.adaptive{
|
||||
display:grid;
|
||||
grid-template-columns: auto;
|
||||
grid-template-rows: auto;
|
||||
grid-template-areas: "content";
|
||||
position:relative;
|
||||
>*{
|
||||
grid-area: content;
|
||||
}
|
||||
> span{
|
||||
opacity: 0;
|
||||
z-index: -10;
|
||||
@extend %base-border;
|
||||
text-transform: initial;
|
||||
border-radius:0px;
|
||||
}
|
||||
}
|
||||
.adaptive--text{
|
||||
min-height:4rem;
|
||||
}
|
||||
.adaptive--text__span{
|
||||
white-space: pre-wrap;
|
||||
padding:2px;
|
||||
}
|
||||
.adaptive--text__textarea{
|
||||
width:100%;
|
||||
height:100%;
|
||||
resize: none;
|
||||
}
|
||||
.adaptive--text__textarea,
|
||||
.adaptive--input__input{
|
||||
position:absolute;
|
||||
}
|
||||
.adaptive--input__input{
|
||||
width:100%;
|
||||
}
|
||||
.adaptive--input__span{
|
||||
padding:2px;
|
||||
min-height:1.5rem;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,60 @@
|
||||
//- Creates our basic border for inputs
|
||||
%inputHighlight{
|
||||
border-width: 1px 3px;
|
||||
border-style: solid;
|
||||
border-color: var(--borderColor);
|
||||
border-radius: 5px;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
%base-border{
|
||||
border-width: 1px 3px;
|
||||
border-style: solid;
|
||||
border-radius: 5px;
|
||||
border-color: transparent;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
//- Styling for elements that should have a box around them
|
||||
%boxed{
|
||||
border: 2px solid var(--borderColor);
|
||||
border-radius:0;
|
||||
box-sizing:border-box;
|
||||
}
|
||||
%borderStyles{
|
||||
.boxed,
|
||||
.sheet-boxed{
|
||||
@extend %boxed;
|
||||
&.thick-left{
|
||||
border-left-width: 5px;
|
||||
}
|
||||
&.thick-bottom{
|
||||
border-bottom-width: 5px;
|
||||
}
|
||||
&.thick-right{
|
||||
border-right-width: 5px;
|
||||
}
|
||||
&.thick-top{
|
||||
border-top-width: 5px;
|
||||
}
|
||||
}
|
||||
.underlined,
|
||||
.sheet-underlined{
|
||||
@extend %base-border;
|
||||
border-radius: 0;
|
||||
border-bottom: 1px solid var(--borderColor);
|
||||
transition: var(--focusTrans);
|
||||
}
|
||||
:is(.underlined,.boxed){
|
||||
&:not([readonly]):not([type='checkbox']):not([type='radio']):is(:hover, :focus,:focus-within){
|
||||
@extend %inputHighlight;
|
||||
}
|
||||
&:not([readonly]):not([type='checkbox']):not([type='radio']):is(:focus,:focus-within){
|
||||
background-color: var(--subHeadBackColor);
|
||||
}
|
||||
}
|
||||
.underlined--invisible{
|
||||
border-color:transparent !important;
|
||||
}
|
||||
}
|
||||
%sectionBoxShadow{
|
||||
box-shadow: rgba(0, 0, 0, 0.16) 0px 3px 6px, rgba(0, 0, 0, 0.23) 0px 3px 6px;
|
||||
}
|
||||
@@ -0,0 +1,81 @@
|
||||
@use 'textLevel';
|
||||
@use 'borderPlaceholders';
|
||||
//- Our basic button styling
|
||||
%base-button{
|
||||
background-color: #DCDCDC33;
|
||||
border-radius: 5px;
|
||||
box-shadow: 0 2px 4px black;
|
||||
border-width: 0;
|
||||
transition: {
|
||||
property:box-shadow,backdrop-filter;
|
||||
duration:200ms;
|
||||
timing-function:ease-out;
|
||||
};
|
||||
backdrop-filter:blur(1px);
|
||||
overflow:hidden;
|
||||
&:is(:hover,:focus){
|
||||
background-color: #85858580;
|
||||
box-shadow: 0 4px 6px black;
|
||||
backdrop-filter:blur(2px);
|
||||
}
|
||||
&:active{
|
||||
background-color: #858585ff;
|
||||
box-shadow: 0 1px 2px black;
|
||||
backdrop-filter:blur(0px);
|
||||
}
|
||||
}
|
||||
//- Styling for our dice buttons
|
||||
%die-button{
|
||||
@extend %base-button;
|
||||
line-height: 14px;
|
||||
/*height to vertically center a 2rem dicefontd10*/
|
||||
font-size: 2rem;
|
||||
font-weight: normal;
|
||||
font-style: normal;
|
||||
padding: 5px 3px 7px;
|
||||
}
|
||||
//- styling for buttons that have standard text in them
|
||||
%text-button{
|
||||
padding: 5px 7px;
|
||||
@extend %base-button;
|
||||
}
|
||||
//- Styling for our roll buttons
|
||||
%roller{
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
align-self:start;
|
||||
gap: var(--half-gap);
|
||||
color:var(--fontColor);
|
||||
&:before{
|
||||
content:'L';
|
||||
font-family:dicefontd6;
|
||||
}
|
||||
}
|
||||
%button{
|
||||
button{
|
||||
cursor: pointer;
|
||||
}
|
||||
.roller{
|
||||
display:flex;
|
||||
gap:var(--half-gap);
|
||||
align-items:center;
|
||||
&:before{
|
||||
font-family:dicefontd20;
|
||||
content:'T'
|
||||
}
|
||||
}
|
||||
.control-button{
|
||||
@extend %inputHighlight;
|
||||
align-self:center;
|
||||
padding-inline:var(--tiny-gap);
|
||||
transition: {
|
||||
property: background-color, color;
|
||||
duration: var(--revealTime);
|
||||
timing-function: ease;
|
||||
}
|
||||
&:hover{
|
||||
background-color:var(--borderColor);
|
||||
color:var(--backColor);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,83 @@
|
||||
@use 'borderPlaceholders';
|
||||
@use 'materialIcons';
|
||||
%collapsible{
|
||||
.collapse-container{
|
||||
position:relative;
|
||||
}
|
||||
.text-collapse{
|
||||
cursor:pointer;
|
||||
display:flex;
|
||||
justify-content:flex-start;
|
||||
align-items:center;
|
||||
&:before{
|
||||
content:'unfold_less';
|
||||
@extend %materialStyle;
|
||||
}
|
||||
}
|
||||
.text-collapse__text{
|
||||
display:inline;
|
||||
}
|
||||
.text-collapse__check{
|
||||
&:not(:checked) + .text-collapse{
|
||||
@extend %inputHighlight;
|
||||
}
|
||||
&:checked + .text-collapse:before{
|
||||
content:'unfold_more';
|
||||
}
|
||||
}
|
||||
.repitem,
|
||||
.collapse-container{
|
||||
&:hover{
|
||||
.collapse,.roll-container{
|
||||
opacity:1;
|
||||
}
|
||||
}
|
||||
.collapse{
|
||||
opacity:0;
|
||||
position:absolute;
|
||||
right:-10px;
|
||||
top:0px;
|
||||
border:0px solid black;
|
||||
border-radius:0;
|
||||
color:var(--selectedColor);
|
||||
text-transform:none;
|
||||
background-color:transparent;
|
||||
&:before{
|
||||
content:'y';
|
||||
font-family:pictos;
|
||||
}
|
||||
&:checked{
|
||||
color:var(--unselectedColor1);
|
||||
background-color:transparent;
|
||||
~ .expanded,
|
||||
~ .collapse-container .expanded{
|
||||
display:none !important;
|
||||
}
|
||||
~ .expanded--empty:is(:not([value]),[value='']) + *,
|
||||
~ .collapse-container ~ .expanded--empty:is(:not([value]),[value='']) + *{
|
||||
display:none !important;
|
||||
}
|
||||
}
|
||||
&:not(:checked){
|
||||
~ .collapsed,
|
||||
~ .collapse-container .collapsed{
|
||||
display:none !important;
|
||||
}
|
||||
}
|
||||
&:hover{
|
||||
color:var(--selectedColor);
|
||||
}
|
||||
}
|
||||
}
|
||||
.repcontainer.editmode{
|
||||
.collapse{
|
||||
display:none;
|
||||
}
|
||||
}
|
||||
.section-control:not(:checked) + .section-display{
|
||||
display:none !important;
|
||||
}
|
||||
.empty-hider:is([value=''],:not([value])) + *{
|
||||
display:none;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
//- A placeholder for creating a stackable grid of elements. Particularly for making stacked input labels.
|
||||
%darkmodeStyle{
|
||||
--borderColor: var(--dark-secondarytext);//Our basic border color
|
||||
--fontColor: var(--dark-secondarytext);//Our basic font color
|
||||
--backColor: var(--dark-surface1);//Set our background to match the dark mode background of the sheet
|
||||
--selectedColor:var(--fontColor);
|
||||
--subHeadBackColor:var(--dark-primary);
|
||||
--checkColor: var(--darkCheck);
|
||||
img{
|
||||
filter: brightness(.8) contrast(1.2);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
//Our various fonts that can be used on the sheet. For now, these are all set to Arial until we find fonts we like, which won't be done until the very end.
|
||||
%font-vars{
|
||||
--topHeaderFont:Arial;
|
||||
--midHeaderFont:Arial;
|
||||
--contentFont:Arial;
|
||||
}
|
||||
%universalVariables{
|
||||
// Layout variables
|
||||
--grid-gap: 1rem;//Variable to define our basic gap between layout elements. Followed by several gaps that are mathematically related to it.
|
||||
--half-gap: calc(var(--grid-gap) / 2);
|
||||
--tiny-gap: calc(var(--half-gap) / 2);
|
||||
--big-gap: calc(var(--grid-gap) * 2);
|
||||
--spanSectionColumn:1/-1;//How a section should span when it is meant to span large numbers of columns (default span all)
|
||||
--fillLeftRadioSize: 1rem;
|
||||
--fillLeftRadioWidth:var(--fillLeftRadioSize);
|
||||
--fillLeftRadioHeight:var(--fillLeftRadioSize);
|
||||
|
||||
// Animation variables
|
||||
--revealTime: 500ms;//Our basic reveal time for transitions
|
||||
--delayTime: 200ms;//Our basic delay time before a transition occurs
|
||||
--inputSwap: opacity var(--revealTime) ease var(--delayTime);//Transition properties for swapping the visibility of two elements
|
||||
--focusTiming: 500ms ease;//our basic timing for the transition used when an element is focused or hovered on
|
||||
--focusTrans: all var(--focusTiming);//The full transition properties for focusing/hovering on an element
|
||||
|
||||
// color variables
|
||||
--borderColor: black;//Our basic border color
|
||||
--fontColor: black;//Our basic font color
|
||||
--backColor: #ffffff;//Our basic background color
|
||||
--subHeadBackColor:grey;//Our sub header background color
|
||||
--unselectedColor1:lightgrey;//Our default font color for items that are currently inactive
|
||||
--unselectedColor2:transparent;
|
||||
--selectedColor:black;
|
||||
--checkColor:black;
|
||||
--darkCheck:white;
|
||||
|
||||
// Border sizing variables
|
||||
--displayBorderWidth: 2px;//Our default border width
|
||||
@extend %font-vars;
|
||||
}
|
||||
@@ -0,0 +1,74 @@
|
||||
@use 'button';
|
||||
|
||||
@mixin repButton{
|
||||
opacity:0;
|
||||
transition: {
|
||||
property:opacity,background-color;
|
||||
duration: var(--revealTime);
|
||||
};
|
||||
@extend %text-button;
|
||||
font-family:pictos;
|
||||
}
|
||||
%fieldsetStyling{
|
||||
.repitem{
|
||||
> input:not([type='checkbox']){
|
||||
width:100%;
|
||||
}
|
||||
.headed-textarea,
|
||||
.description{
|
||||
grid-column:1/-1;
|
||||
}
|
||||
}
|
||||
.repcontainer{
|
||||
display:grid;
|
||||
gap:var(--grid-gap);
|
||||
}
|
||||
.repeating-container{
|
||||
display:grid;
|
||||
grid-template-areas:'header';
|
||||
align-self:start;
|
||||
> .header{
|
||||
grid-area:header;
|
||||
}
|
||||
&:is(:hover,:focus-within,:focus){
|
||||
.repcontrol_edit:after,
|
||||
.repcontrol-button{
|
||||
opacity:1;
|
||||
}
|
||||
}
|
||||
}
|
||||
.repcontrol_edit{
|
||||
visibility:hidden;
|
||||
text-transform:none;
|
||||
&:after{
|
||||
@include repButton;
|
||||
visibility:visible;
|
||||
content:'p';
|
||||
}
|
||||
}
|
||||
.repcontrol-button{
|
||||
grid-area:header;
|
||||
align-self:start;
|
||||
~ .repcontrol{
|
||||
display:contents;
|
||||
.repcontrol_edit{
|
||||
grid-area:header;
|
||||
align-self:start;
|
||||
justify-self:end;
|
||||
display:flex;
|
||||
float:none;
|
||||
}
|
||||
.repcontrol_add{
|
||||
display:none !important;
|
||||
}
|
||||
}
|
||||
}
|
||||
.repcontrol-button--add{
|
||||
justify-self:start;
|
||||
@include repButton;
|
||||
&:before{
|
||||
font-family:pictos;
|
||||
content:'&';
|
||||
}
|
||||
}
|
||||
}
|
||||