Compare commits

...

53 Commits
v0.8 ... main

Author SHA1 Message Date
93800c2706 Provide mechanism to get tab click (Fixes #4) 2025-01-30 23:00:03 -05:00
67c857bbed Remove the alert in one click select 2025-01-30 19:24:11 -05:00
516b0fe4df Add intro to explain the project 2025-01-11 13:08:34 -05:00
b5e0061247 Add code to auto select tabs 2025-01-11 13:03:27 -05:00
a8cd90c349 Fixes #25 Javascript to redirect into the ds 2024-11-08 12:18:26 -05:00
be90329514 sublime-Workspace just changed 2024-10-18 23:21:30 -04:00
d64bb5e7a2 Readme addtiions 2024-10-18 23:20:01 -04:00
f842822915 Clean up lines from intersection observer testing. 2024-10-18 18:44:04 -04:00
c0aa93a3c1 Fixes #20 core.cookie.remove now sets the value and the date of the date object to null which deletes the cookie. 2024-10-18 18:39:38 -04:00
7dcc72d5a0 Fixes #24 - Expose oneClickSelect 2024-10-18 18:25:40 -04:00
f70d94ea67 Fixes #21 2024-10-18 18:19:40 -04:00
339e177ac4 Fixes #23 2024-10-18 09:28:55 -04:00
197e6f2f33 #20 should be fixed but needs testing 2024-10-02 10:07:51 -04:00
bcbe51e9a7 Fix error and reinitialize getcss function (reopens #14) 2024-09-23 11:40:09 -04:00
559552f218 Fixes #17 - styles not correct for colour cards when using text that is too large 2024-09-18 09:22:11 -04:00
2cd25ad7bd Fixes #18 2024-09-16 16:29:32 -04:00
f358266533 Fixes #17 - add variable for colour text 2024-09-16 09:53:49 -04:00
b5ab99da8d Fixes #12 in the tab 2024-09-13 11:00:52 -04:00
5fa631a903 Fixes #12 2024-09-13 10:45:55 -04:00
c201ff8f63 Fixes #11 Second Parameter to false will not add spacer li 2024-09-03 17:55:37 -04:00
2c117442af Fixes #10 Force status for core patterns to complete 2024-09-03 17:43:07 -04:00
b60c118e41 Add font to tooltip 2024-08-21 13:30:10 -04:00
acdb794971 Move get url to self referential function 2024-08-20 13:08:46 -04:00
140b239cfc Update to allow tab and space or enter to select a tab and change copyright info 2024-08-16 21:10:37 -04:00
a60f831900 Add getCSS 2024-08-07 08:08:59 -04:00
ea92f5e7ac Update patterns use paths to match what download.php gives 2024-07-29 19:12:22 -04:00
3292729d53 Update pattern documentation 2024-07-28 15:30:51 -04:00
77a13bbd46 Update to handle multiple level statuses. 2024-07-25 17:21:52 -04:00
bdb7f0e0aa Fixed typo 2024-07-23 21:18:17 -04:00
0b82aa4be6 Update div.tab-group to use tabset 2024-07-23 20:50:36 -04:00
fd53ee174a Fixes #2 for performances issues 2024-07-23 18:08:37 -04:00
c94d5e565f Fixes #5 Update sort 2024-07-22 18:39:14 -04:00
552a204edd Fixes #5 Update to include display text in status an alpha reports 2024-07-22 18:24:29 -04:00
e7d4e2ab48 Added bootstrap comment 2024-07-22 12:01:15 -04:00
fa165d530f Added XXL breakpoint to match bootstrap v5.0 2024-07-22 12:00:26 -04:00
74fc7a4c11 Fixes #3 - Added instructions to readme.md 2024-07-16 04:06:19 -04:00
9cba20c39c Completed descriptions for layout patterns 2024-07-16 03:57:34 -04:00
3c261881e9 Update switches to include breakpoints 2024-07-16 03:44:48 -04:00
c0ea225d03 Update tooltip, mark complete 2024-07-16 03:44:20 -04:00
ce98e0c488 Update switch - set to done 2024-07-16 03:11:51 -04:00
fa708175b7 Move pug pattern files to .pp, check tab order 2024-07-16 02:49:53 -04:00
0036bcf0fd Fixes #2 interaction observer unobserving and loading before on page. 2024-07-15 12:24:35 -04:00
0708328647 Move unobserve to unobserve all patterns after a load's ready state is done.
Safe to assume that unless you're still copying the design system to some place that the result won't be any different. Since that is such an edge case a page reload should suffice.
2024-07-15 09:27:06 -04:00
74abc40dc4 Stop observing loaded patterns 2024-07-15 09:17:22 -04:00
4c394e5215 Temp fix for compile bug 2024-07-15 07:57:46 -04:00
1c0186d4fe Update ajax to use intersection observer 2024-07-14 21:52:51 -04:00
2f4c21397b Update defaults to use colours rather than colour vars. 2024-07-14 19:21:21 -04:00
7b935d1a85 Update defaults to use colours rather than colour vars. 2024-07-14 19:20:54 -04:00
7b965d18f7 Removed out of context a
Can't call an article outside of the query selector all. As this should only run once, you'd need to address the specific article.
2024-07-14 16:36:11 -04:00
9c15304340 Fixed bugs and updated structure 2024-07-14 16:18:52 -04:00
51c2c569b8 Fix bad path 2024-07-13 20:50:35 -04:00
a08cfbafa0 fix bad path 2024-07-13 20:49:33 -04:00
352147b7e2 Move the menu stuff to a handler called page. 2024-07-13 20:22:50 -04:00
85 changed files with 5590 additions and 2659 deletions

View File

@ -1,16 +1,103 @@
# DS2 Core
# DS2-core
DS2-core is a lightweight PugJS-based framework for building design systems.
The design system compiles to mostly pure HTML, SCSS and JavaScript. There are a few enhanced parts that use PHP in order to handle non-critical tasks Zip files on the fly to collect component JavaScript and SCSS. PugJS is used because it can handle some of the automation such as creating includes making components extremely modular.
## Requirements
The requirements for ds2-core are pretty light. You'll want to be able to process [PugJS](https://pugjs.org/api/getting-started.html) (formerly Jade) and [SCSS](https://sass-lang.com/documentation/) -- and that's about it.
For our own design system, we use ds2-core with [Prepros](https://prepros.io) (which you can use the Free Unlimited Trial for, but why not splurge and spend the $30USD to support the developer and skip the nags). On MacOS, you could also use [CodeKit](https://codekitapp.com/).
Alternatively, if you have pre-processor pipelines for Pug and SCSS, which you can install using npm, or any other language you decide to pull in, you can use those to compile if that ends up being easier for you. The framework isn't too picky, so long as things go into the right place.
## "Installation"
File | Processes to
------------------------------|------------------------------
src/js/scaffolding.js | public/assets/
src/scss/scaffolding.scss | public/assets/
src/pg/core/core.scss.pug | src/scss/
src/pg/core/download.php.pug | public
All other pug files should compile to from src/pg/ to a relative path of public/*
## Running the core
### Callback functions
Callback functions can be used in
- beforeArticleLoad - called before any patterns have started to load
- success - called when loading a pattern is successful if the result is an HTTP 200
- afterArticleLoad - called after any patterns have started to load
- done - called when the ajax for any pattern is done, whether successful or not. This is a useful place to load any javascript initializations that pattern.
## Creating an item
## About the content variable
## The content object
The content variable in \_config.pug defines your array of patterns. It is made up of the following attributes:
The content variable in \/src\/pg\/_config.pug defines your array of patterns. It is made up of the following attributes:
- name - the hypenated name of the pattern
- status - this should be one of the statuses from your status array
- display - (optional) if present this will be displayed, as is, instead of the name
- template - (optional) [ pug (default) | md ] the file type of a pattern's index file
- core - (optional ) [ true | false ] if true, it will pull from the core folder
- files - (optional) an array of patterns under the parent.
By changing and resaving the \_config.pug file, (our change is often adding or removing a random space) all of the pug patterns will recompile. Note that md templates will not recompile automatically when config is saved and updated as markdown files don't have an include.
## Including PugJS in Pug files without compiling
If you wish to include Pug output as code in your instance, you can do this without manually creating a second 'dot container' version of the file. Including files with 'unrecognised' extensions does not compile them.
1. In your project config, create a Custom Tool called Pug pattern to pug file
1. Check Process automatically and set the command to 'cp {{input}} {{output}}' on Mac/Linux and 'copy {{input}} {{output}}' on Windows. (This is just your operating system's command line file copy executable.)
1. Set the Output to Relative to input
1. Set the Output Extension to .pug
In your design system implementation,
1. Create the files that you edit as _[pattern].pp files, and set them to auto compile. (You may wish to let your text editor know what they are, so the syntax highlighting works.
1. Save the file, ensure that it is set to in prepros it is set to process automatically.
1. Include the .pp file as your pug pattern with .language-pug and include the .pug file as your html output.
This will ensure that the .pug file will get processed and the .pp file will be handled as text will get compiled, but they should display correctly and remain in sync while maintaining the minimum number of files.
## Using core code with your own pattern documentation.
Using
---
Creating a new pattern
Begin by creating a folder within your strucutre to hold the pattern. Add the folder to your config file.
Generating css
You've likely created your component's css as an include file beginning with an underscore. create a second file named the same that includes any dependencies (such as breakpoints) that are required to generate your valid css.
You can now include the css in your pattern's index file.
Generating pug
Create a custom tool in prepros, give it a name such as "PP to Pug" set the input extension to .pp and the output extension to .pug and check Process Automatically . The command should be
Mac / Linux
cp {{input}} {{output}}
Windows
copy {{input}} {{output}}
Once you've added the tool, set the output to "relative path" and set the output extension to pug. For each .pp file you may have to check process automatically as it doesn't always identify the new extension.
You will now be able to include the .pp file in your pattern's index file while including the .pug file which will give a compiled version of your component's html.
---
## Troubleshooting
## Credits
This framework includes [PrismJS](https://prismjs.com/) for code syntax highlighting. PrismJS is released under the [MIT license](https://opensource.org/licenses/MIT)>

View File

@ -2,7 +2,11 @@
"folders":
[
{
"path": "."
"path": ".",
"folder_exclude_patterns": ["src/pg/patterns"]
},
{
"path": "./src/pg/patterns"
}
],
}

View File

@ -281,17 +281,14 @@
"expanded_folders":
[
"/Users/am/Desktop/ds2-core",
"/Users/am/Desktop/ds2-core/src",
"/Users/am/Desktop/ds2-core/src/pg",
"/Users/am/Desktop/ds2-core/src/pg/patterns",
"/Users/am/Desktop/ds2-core/src/pg/patterns/core",
"/Users/am/Desktop/ds2-core/src/pg/patterns/core/components",
"/Users/am/Desktop/ds2-core/src/pg/patterns/core/components/sticky-note",
"/Users/am/Desktop/ds2-core/src/pg/patterns/core/components/switch",
"/Users/am/Desktop/ds2-core/src/pg/patterns/core/components/tooltip"
"/Users/am/Desktop/ds2-core/src/pg/patterns"
],
"file_history":
[
"/Users/am/Desktop/ds2-core/src/js/scaffolding.js",
"/Users/am/Desktop/ds2-core/src/js/core/_core.js",
"/Users/am/Desktop/ds2-core/Readme.md",
"/Users/am/Desktop/ds2-core/src/pg/core/_colour-samples.pug",
"/Users/am/Desktop/ds2-core/src/pg/patterns/core/components/switch/index.pug",
"/Users/am/Desktop/ds2-core/src/pg/patterns/core/components/sticky-note/index.pug",
"/Users/am/Desktop/ds2-core/src/pg/patterns/core/layouts/breakpoints/index.pug",
@ -415,15 +412,11 @@
"/Users/am/Desktop/my DS2/src/pg/patterns/components/tooltip/index.pug",
"/Users/am/Desktop/my DS2/src/pg/patterns/components/link/index.pug",
"/Users/am/Desktop/my DS2/src/pg/patterns/components/progress-bar/index.pug",
"/Users/am/Desktop/my DS2/src/pg/patterns/layouts/main-navigation/index.pug",
"/Users/am/Desktop/my DS2/src/pg/patterns/layouts/breakpoints/index.pug",
"/Users/am/Desktop/my DS2/src/pg/patterns/visual-design/notifications/index.pug",
"/Users/am/Desktop/my DS2/src/pg/patterns/visual-design/spacing/spacing.css",
"/Users/am/Desktop/my DS2/src/pg/patterns/visual-design/colours/index.pug"
"/Users/am/Desktop/my DS2/src/pg/patterns/layouts/main-navigation/index.pug"
],
"find":
{
"height": 26.0
"height": 24.0
},
"find_in_files":
{
@ -438,6 +431,7 @@
"case_sensitive": false,
"find_history":
[
"oneClickSelect",
"../core/_master-pattern.pug",
"../core",
"hide-deprecated",
@ -511,7 +505,7 @@
],
"incremental_find":
{
"height": 26.0
"height": 24.0
},
"input":
{
@ -556,7 +550,7 @@
"project": "ds2 core.sublime-project",
"replace":
{
"height": 68.0
"height": 44.0
},
"save_all_on_build": false,
"select_file":

View File

@ -492,6 +492,9 @@
"resolveJsonModule": false,
"esModuleInterop": false,
"useDefineForClassFields": false
},
"custom-gzg6caunrh": {
"command": "cp {{input}} {{output}}"
}
},
"fileTypes": {
@ -955,6 +958,26 @@
"type": "SOURCE_RELATIVE",
"relativePath": ""
}
},
"custom-sm9kzo2npr": {
"autoCompile": true,
"label": "Pug pattern to pug file",
"extensions": [
".pp"
],
"tasks": [
{
"task": "custom-gzg6caunrh",
"enable": true
}
],
"output": {
"extension": ".pug",
"type": "SOURCE_RELATIVE",
"relativePath": "",
"suffix": "-dist",
"alwaysSuffix": false
}
}
},
"files": [
@ -1184,6 +1207,9 @@
"concat-js": {
"enable": false
},
"babel": {
"enable": true
},
"bundle-js": {
"enable": true,
"options": {
@ -1191,6 +1217,7 @@
}
},
"minify-js": {
"enable": false,
"options": {
"toplevel": true
}
@ -1345,6 +1372,30 @@
}
}
},
{
"file": "src/pg/patterns/core/sticky-note/_sticky-note.pp",
"config": {
"autoCompile": true
}
},
{
"file": "src/pg/patterns/core/switch/_switch.pp",
"config": {
"autoCompile": true
}
},
{
"file": "src/pg/patterns/core/tabs/_tabs.pp",
"config": {
"autoCompile": true
}
},
{
"file": "src/pg/patterns/core/tooltip/_tooltip.pp",
"config": {
"autoCompile": true
}
},
{
"file": "src/pg/patterns/layouts/header-core/header.scss",
"config": {
@ -1494,16 +1545,6 @@
"config": {
"customOutput": "src/scss/_status.scss"
}
},
{
"file": "src/scss/scaffolding.scss",
"config": {
"tasks": {
"minify-css": {
"enable": false
}
}
}
}
]
}

Binary file not shown.

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

52
public/download.php Normal file
View File

@ -0,0 +1,52 @@
<?php
function recursor($dir, $type) {
$result = array();
// create the pattern to get the type
$x = "/_*.";
for ($i = 0; $i < strlen($type); $i++){
$x .= "[" . strtolower($type[$i]) . strtoupper($type[$i]) ."]";
}
// get the directories
foreach(glob($dir . "/*") as $d) {
if ( is_dir( $d ) ) {
// find the files in each directory
foreach (glob($d . $x) as $f) {
$result[] = $f;
}
// $more = recursor($d, $type);
// $result = array_merge($result, $more);
$result = array_merge($result, recursor($d, $type));
}
}
return $result;
}
$allowed_types = ["scss", "js"];
$patterns = dirname(dirname(__file__)) . "/src/pg/patterns";
if (!isset($_SERVER['QUERY_STRING']) || !in_array($_SERVER['QUERY_STRING'], $allowed_types)) {
echo "File extension type is not defined. Ensure that you have added ?[file extension] to the URL. If you have defined a file extension and it is not allowed, you'll need to contact the an administrator to get the requested files.";
die();
}
$type = $_SERVER['QUERY_STRING'];
$file_list = recursor($patterns, $type);
$f = tmpfile();
$t = stream_get_meta_data($f)['uri'];
$z = new ZipArchive();
$zf = $z->open($t, ZipArchive::CREATE);
foreach($file_list as $f) {
$z->addFile($f, preg_replace('/^.*?patterns\//', '', $f));
}
$z->close();
header('Content-type: application/zip');
header(sprintf('Content-Disposition: attachment; filename="%s.zip"', $type));
echo(file_get_contents($t)); ?>

View File

@ -8,9 +8,14 @@
<link rel="icon" href="https://assets.gamv.ca/favicon.svg" media="(prefers-color-scheme:no-preference),(prefers-color-scheme:light)">
<link rel="icon" href="https://assets.gamv.ca/favicon-dark.svg" media="(prefers-color-scheme:dark)">
<link href="assets/scaffolding.css" rel="stylesheet">
<script src="assets/jquery-min.js"></script>
</head>
<body><a class="skip" href="#main">Skip to main content</a>
<body>
<!--
DS2 core (c) 2024 Alexander McIlwraith
Core licensed under CC BY-SA 4.0
--><a class="skip" href="#main">Skip to main content</a>
<div class="container">
<header>
<!-- The headline banner area -->
@ -19,67 +24,67 @@
</svg>
<div>
<div class="header-title">
<h1> <a>DS2 core</a></h1>
<h1> <a href="./">DS2 core</a></h1>
</div>
<!-- Other sections can go here, such as search and directory-->
</div>
</header>
<nav>
<ul>
<li> <a href="./">Home</a></li>
<li><a href="./?p=this-pattern-doesn't-exist">This pattern doesn't exist</a></li>
<li><a href="./?p=this-pattern-doesnt-exist">This pattern doesn't exist</a></li>
<li><a href="./?p=colours">Colours</a></li>
<li><a href="./?p=components">Components</a></li>
<li><a href="./?p=layouts">Layouts</a></li>
<li><a href="./?p=status">Status</a></li>
</ul>
</nav>
<p class="deprecated-switch"><span></span><span id="deprecated" role="switch"></span>
<label for="deprecated">Show deprecated patterns</label>
<p class="info-switches"><span></span><span id="deprecated" role="switch"></span>
<label for="deprecated">Show deprecated patterns</label><span></span><span id="breakpoints" role="switch"></span>
<label for="breakpoints">Show breakpoint information</label>
</p>
<main id="main">
<h1>DS2 core</h1>
<article class="status-deprecated" id="this-pattern-doesn't-exist" data-path="this-pattern-doesn't-exist" data-template="pug" data-pattern="this-pattern-doesn't-exist" data-status="deprecated" data-core="false">
<article id="this-pattern-doesnt-exist" data-name="this pattern doesn't exist" data-status="deprecated" data-template="pug" data-core="false" data-path="this-pattern-doesnt-exist" style="height: 100vh">
<h1 class="status-deprecated"><span>This pattern doesn't exist
<tool-tip role="tooltip" inert="inert" tip-position="right">Deprecated</tool-tip></span></h1>
</article>
<article id="colours" data-path="colours" data-template="pug" data-pattern="colours" data-status="complete" data-core="true">
<article id="colours" data-name="colours" data-status="complete" data-template="pug" data-core="true" data-path="colours" style="height: 100vh">
<h1 class="status-complete"><span>Colours
<tool-tip role="tooltip" inert="inert" tip-position="right">Complete</tool-tip></span></h1>
</article>
<article id="components" data-path="components" data-template="none" data-pattern="components" data-status="complete" data-core="false">
<article id="components" data-name="components" data-status="complete" data-template="none" data-core="false" data-path="components" style="height: 100vh">
<h1 class="status-complete"><span>Components
<tool-tip role="tooltip" inert="inert" tip-position="right">Complete</tool-tip></span></h1>
</article>
<article id="components-sticky-note" data-path="components/sticky-note" data-template="pug" data-pattern="sticky-note" data-status="in-progress" data-core="true">
<h1 class="status-in-progress"><span>Sticky note
<tool-tip role="tooltip" inert="inert" tip-position="right">In progress</tool-tip></span></h1>
<article id="components-sticky-note" data-name="sticky-note" data-status="complete" data-template="pug" data-core="true" data-path="components/sticky-note" style="height: 100vh">
<h1 class="status-complete"><span>Sticky note
<tool-tip role="tooltip" inert="inert" tip-position="right">Complete</tool-tip></span></h1>
</article>
<article id="components-switch" data-path="components/switch" data-template="pug" data-pattern="switch" data-status="in-progress" data-core="true">
<h1 class="status-in-progress"><span>Switch
<tool-tip role="tooltip" inert="inert" tip-position="right">In progress</tool-tip></span></h1>
<article id="components-switch" data-name="switch" data-status="complete" data-template="pug" data-core="true" data-path="components/switch" style="height: 100vh">
<h1 class="status-complete"><span>Switch
<tool-tip role="tooltip" inert="inert" tip-position="right">Complete</tool-tip></span></h1>
</article>
<article id="components-tooltip" data-path="components/tooltip" data-template="pug" data-pattern="tooltip" data-status="in-progress" data-core="true">
<h1 class="status-in-progress"><span>Tooltip
<tool-tip role="tooltip" inert="inert" tip-position="right">In progress</tool-tip></span></h1>
<article id="components-tooltip" data-name="tooltip" data-status="complete" data-template="pug" data-core="true" data-path="components/tooltip" style="height: 100vh">
<h1 class="status-complete"><span>Tooltip
<tool-tip role="tooltip" inert="inert" tip-position="right">Complete</tool-tip></span></h1>
</article>
<article id="layouts" data-path="layouts" data-template="none" data-pattern="layouts" data-status="complete" data-core="true">
<article id="layouts" data-name="layouts" data-status="complete" data-template="none" data-core="true" data-path="layouts" style="height: 100vh">
<h1 class="status-complete"><span>Layouts
<tool-tip role="tooltip" inert="inert" tip-position="right">Complete</tool-tip></span></h1>
</article>
<article id="layouts-header" data-path="layouts/header" data-template="pug" data-pattern="header" data-status="in-progress" data-core="true">
<h1 class="status-in-progress"><span>Header
<tool-tip role="tooltip" inert="inert" tip-position="right">In progress</tool-tip></span></h1>
<article id="layouts-header" data-name="header" data-status="complete" data-template="pug" data-core="true" data-path="layouts/header" style="height: 100vh">
<h1 class="status-complete"><span>Header
<tool-tip role="tooltip" inert="inert" tip-position="right">Complete</tool-tip></span></h1>
</article>
<article id="layouts-breakpoints" data-path="layouts/breakpoints" data-template="pug" data-pattern="breakpoints" data-status="in-progress" data-core="true">
<h1 class="status-in-progress"><span>Breakpoints
<tool-tip role="tooltip" inert="inert" tip-position="right">In progress</tool-tip></span></h1>
<article id="layouts-breakpoints" data-name="breakpoints" data-status="complete" data-template="pug" data-core="true" data-path="layouts/breakpoints" style="height: 100vh">
<h1 class="status-complete"><span>Breakpoints
<tool-tip role="tooltip" inert="inert" tip-position="right">Complete</tool-tip></span></h1>
</article>
<article id="layouts-tabs" data-path="layouts/tabs" data-template="pug" data-pattern="tabs" data-status="complete" data-core="true">
<article id="layouts-tabs" data-name="tabs" data-status="complete" data-template="pug" data-core="true" data-path="layouts/tabs" style="height: 100vh">
<h1 class="status-complete"><span>Tabs
<tool-tip role="tooltip" inert="inert" tip-position="right">Complete</tool-tip></span></h1>
</article>
<article id="status" data-path="status" data-template="pug" data-pattern="status" data-status="complete" data-core="true">
<article id="status" data-name="status" data-status="complete" data-template="pug" data-core="true" data-path="status" style="height: 100vh">
<h1 class="status-complete"><span>Status
<tool-tip role="tooltip" inert="inert" tip-position="right">Complete</tool-tip></span></h1>
</article>

View File

@ -5,14 +5,24 @@
</head>
<body data-prismjs-copy-timeout="1500">
<h2>What is it</h2>
<p>Breakpoints enable responsive mobile design.</p>
<h2>When to use it</h2>
<p>Use breakpoints when designing for different screen sizes. </p>
<p>The breakpoints SCSS mixin included implements media queries to allow for the change of the layout and design based on pre-defined screen sizes. </p>
<h2>How to use it</h2>
<p>This pattern is only available for SCSS breakpoints. The mixin is avai</p>
<p>When using this, use the default break points as they are set to the same as the Bootstrap framework. The grid for the design system at large break point has been widened to accompdate 3 colour cards across. </p>
<div class="tab-group" id="breakpoints">
<pre class="language-css" data-tab="scss">//- DS2 core (c) 2024 Alexander McIlwraith
<tabset id="breakpoints">
<div tab="scss">
<pre class="language-sass">@import "[path-to]/breakpoints";
@include break([breakpoint]) {
// css here
}</pre>
<pre class="language-sass">//- DS2 core (c) 2024 Alexander McIlwraith
//- Licensed under CC BY-SA 4.0
$grid-breakpoints: ( xs: 0, sm: 576px, md: 768px, lg: 992px, xl: 1200px ) !default;
// default breakpoints match bootstrap 5 breakpoints.
$grid-breakpoints: ( xs: 0, sm: 576px, md: 768px, lg: 992px, xl: 1200px, xxl: 1400px ) !default;
@mixin breakpoint-debug {
body::before, body::after {
@ -96,5 +106,6 @@ $grid-breakpoints: ( xs: 0, sm: 576px, md: 768px, lg: 992px, xl: 1200px ) !defau
}
}</pre>
</div>
</tabset>
</body>
</html>

View File

@ -4,7 +4,14 @@
<title>Pattern</title>
</head>
<body data-prismjs-copy-timeout="1500">
<h2>Primary colours</h2>
<h2>What is it</h2>
<p>Colours are used to represent your site and are an implementation of your brand's visual identity. </p>
<h2>When to use it</h2>
<p>Colours are used throughout your patterns. </p>
<h2>How to use it</h2>
<p>Hover over the colour gradient sample pills to view the accessibility information for each colour sample against black and white. </p>
<p>Click on the colour name or the colour gradient sample pills to copy the colour to your clipboard. A regular click will copy the hex code, a shift+click will copy the RGB code, the alt key (or Mac option&nbsp;&#8997; key) will copy the colour token, and the meta key (Windows key or Mac command&nbsp;&#8984; key) will copy a CSS colour var. </p>
<h3>Primary colours</h3>
<color-samples>
<color-sample data-color="rgb( 46, 81, 161)" style="background-color: rgb( 46, 81, 161); color: #FFF">
<name data-hex="#2e51a1" data-rgb="rgb( 46, 81, 161)" data-token="--colour-blue"><span>Blue</span></name>
@ -280,23 +287,23 @@
<div class="tab-group" id="colors">
<div data-tab="css">
<pre class="language-css">:root {
--colour-blue: #2e51a1,
--colour-blue-l: #5c7abf,
--colour-blue-xl: #b2c3ec,
--colour-blue-d: #133176,
--colour-blue-xd: #031235,
--colour-blue: #2e51a1;
--colour-blue-l: #5c7abf;
--colour-blue-xl: #b2c3ec;
--colour-blue-d: #133176;
--colour-blue-xd: #031235;
--colour-grey: #7f7f7f,
--colour-grey-l: #b2b2b2,
--colour-grey-xl: #d8d8d8,
--colour-grey-xxl: #f0f0f0,
--colour-white: #fff,
--colour-page: #fff,
--colour-light: #fff,
--colour-grey-d: #4c4c4c,
--colour-grey-xd: #4c4c4c,
--colour-black: #000,
--colour-dark: #000,
--colour-grey: #7f7f7f;
--colour-grey-l: #b2b2b2;
--colour-grey-xl: #d8d8d8;
--colour-grey-xxl: #f0f0f0;
--colour-white: #fff;
--colour-page: #fff;
--colour-light: #fff;
--colour-grey-d: #4c4c4c;
--colour-grey-xd: #4c4c4c;
--colour-black: #000;
--colour-dark: #000;
}</pre>
</div>
<div data-tab="scss">

View File

@ -1,109 +0,0 @@
<html>
<head>
<title>Pattern</title>
</head>
<body data-prismjs-copy-timeout="1500">
<h2>What is it</h2>
<h2>When to use it</h2>
<h2>How to use it</h2>
<h2>Example</h2>
<p class="switch">
<label for="example-switch">Switch label</label><span id="example-switch" role="switch"></span>
</p>
<div class="tab-group" id="switches">
<pre class="language-html" data-tab="html"><span id="example-id" role="switch"></span></pre>
<pre class="language-pug" data-tab="pug">span#example-id(role="switch")</pre>
<pre class="language-css" data-tab="css">[role=switch] {
display: -ms-inline-grid;
display: inline-grid;
border: 1px solid var(--colour-blue);
background-color: var(--colour-grey-xl);
border-radius: 0.75rem;
height: 1.5rem;
width: 3rem;
-webkit-transition: all 500ms;
transition: all 500ms;
}
[role=switch] > span {
display: inline-block;
background-color: white;
border-radius: 50%;
margin: 2%;
width: calc(1.5rem - 2%);
-webkit-transition: all 500ms;
transition: all 500ms;
}
[role=switch][aria-checked=true] {
background-color: var(--colour-blue);
}
[role=switch][aria-checked=true] > span {
margin-left: calc(1.5rem - 5%);
}</pre>
<pre class="language-css" data-tab="scss">//- DS2 core (c) 2024 Alexander McIlwraith
//- Licensed under CC BY-SA 4.0
@use "sass:math";
$switch-accent: var(--colour-blue) !default; // switch background when switched right (on/ true)
$switch-background: var(--colour-grey-xl) !default; // switch background when switched left (off / false)
$switch-color: var(--colour-white) !default; // the colour of the switch
$switch-height: 1.5rem !default;
@mixin switch {
[role='switch'] {
display: inline-grid;
border: 1px solid $switch-accent;
background-color: $switch-background;
border-radius: math.div($switch-height, 2);
height: $switch-height;
width: #{$switch-height * 2};
transition: all 500ms;
> span {
display: inline-block;
background-color: white;
border-radius: 50%;
margin: 2%;
width: calc(#{$switch-height} - 2%);
transition: all 500ms;
}
&[aria-checked="true"] {
background-color: $switch-accent;
> span {
margin-left: calc(#{$switch-height} - 5%);
}
}
}
}</pre>
<pre class="language-js" data-tab="js">//- DS2 core (c) 2024 Alexander McIlwraith
//- Licensed under CC BY-SA 4.0
function flip(e) {
let sw = e.currentTarget;
switch(sw.getAttribute("aria-checked")) {
case "true":
sw.setAttribute("aria-checked", "false");
break;
case "false":
sw.setAttribute("aria-checked", "true");
break;
}
};
function init(callback){
let sw = document.querySelectorAll("[role='switch']");
for (let i=0; i < sw.length; i++) {
sw[i].innerHTML = "<span></span>";
sw[i].setAttribute("aria-checked", "false");
sw[i].setAttribute("tabindex", "0");
sw[i].addEventListener("click", flip, false);
sw[i].addEventListener("keypress", flip, false);
}
}
export {init};</pre>
</div>
</body>
</html>

View File

@ -0,0 +1,106 @@
<html>
<head>
<title>Pattern</title>
</head>
<body data-prismjs-copy-timeout="1500">
<h2>What is it</h2>
<p>A header is layout pattern that helps the user identify the site. </p>
<h2>When to use it</h2>
<p>Use a header at the top of every page. The 'front page' of a site may have a different header than the rest of the pages. </p>
<h2>How to use it</h2>
<p>Place the header at the top of the page after the skip to main content link. You will likely want to replace core header should be replaced with your own site's header. To do this, remove the <code class="inline language-js">core: true </code> and create your own pattern in the location you wish it in your design system. </p>
<tabset id="header">
<pre class="language-html" tab="html">
<!-- create temp variables and store the design system values-->
<header>
<!-- The headline banner area -->
<svg height="5.5rem" width="100%" xmlns="http://www.w3.org/2000/svg" aria-hidden="true">
<text>[site name]</text>
</svg>
<div>
<div class="header-title">
<h1> <a href="./">[site name]</a></h1>
</div>
<!-- Other sections can go here, such as search and directory-->
</div>
</header></pre>
<pre class="language-pug" tab="pug">//- DS2 core (c) 2024 Alexander McIlwraith
//- Licensed under CC BY-SA 4.0
//- required variables
//- site - the site name that goes in the site title
//- root - the path to the root of the site
header
// The headline banner area
svg(height='5.5rem' width='100%' xmlns='http://www.w3.org/2000/svg' aria-hidden='true')
text= site
div
div.header-title
h1
a(href="./")= site
// Other sections can go here, such as search and directory
</pre>
<pre class="language-css" tab="css">header{display:-ms-grid;display:grid;-ms-grid-rows:1.75rem 3.5rem;grid-template-rows:1.75rem 3.5rem;-ms-grid-column:2;-ms-grid-column-span:2;grid-column:2/4;overflow:hidden}header svg{grid-column:1/-1;grid-row:1/-1;-ms-grid-row-align:stretch;-ms-grid-column-align:stretch;place-self:stretch}header svg text{-webkit-transform:translate(-1rem,7.25rem);-ms-transform:translate(-1rem,7.25rem);transform:translate(-1rem,7.25rem);font-size:10rem;font-weight:1000;font-family:sans-serif;fill:var(--colour-grey-xxl)}header>div{-ms-grid-row:2;grid-row:2;grid-column:1/-1;display:-ms-grid;display:grid;grid-column-gap:1rem;-ms-grid-columns:auto -webkit-max-content -webkit-max-content;-ms-grid-columns:auto max-content max-content;grid-template-columns:auto -webkit-max-content -webkit-max-content;grid-template-columns:auto max-content max-content}header>div .header-title h1{margin:0;padding:0 1rem}header>div .header-title h1 a,header>div .header-title h1 a:visited{border-bottom:none;color:var(--colour-black);font-family:sans-serif;font-size:2.5rem;font-size:32px;font-weight:700;margin:0;padding:0;text-decoration:none}</pre>
<div class="language-sass" tab="scss">
<pre class="language-sass">@import "scss/core/header/header;
</pre>
<pre class="language-sass">//- DS2 core (c) 2024 Alexander McIlwraith
//- Licensed under CC BY-SA 4.0
$header-bg-color: var(--colour-grey-xxl) !default;
$font-heading: sans-serif !default;
$font-weight: 700 !default;
@mixin header {
header {
display: grid;
grid-template-rows: 1.75rem 3.5rem;
grid-column: 2 / 4;
overflow: hidden;
svg {
grid-column: 1 / -1;
grid-row: 1 / -1;
place-self: stretch;
text {
transform: translate(-1rem, 7.25rem);
font-size: 10rem;
font-weight: 1000;
font-family: $font-heading;
fill: $header-bg-color;
}
}
> div {
grid-row: 2;
grid-column: 1 / -1;
display: grid;
grid-column-gap: 1rem;
grid-template-columns: auto max-content max-content;
.header-title {
h1 {
margin: 0;
padding: 0 1rem;
a, a:visited {
border-bottom: none;
color: var(--colour-black);
font-family: $font-heading;
font-size: 2.5rem;
font-size: 32px;
font-weight: $font-weight;
margin: 0;
padding: 0;
text-decoration: none;
}
}
}
}
}
}</pre>
</div>
</tabset>
</body>
</html>

View File

@ -1,131 +0,0 @@
<html>
<head>
<title>Pattern</title>
</head>
<body data-prismjs-copy-timeout="1500">
<div class="tab-group" id="header">
<pre class="language-html" data-tab="html">
<!-- create temp variables and store the design system values-->
<header>
<!-- The headline banner area -->
<svg height="5.5rem" width="100%" xmlns="http://www.w3.org/2000/svg" aria-hidden="true">
<text>[site name]</text>
</svg>
<div>
<div class="header-title">
<h1> <a href="[site root]">[site name]</a></h1>
</div>
<!-- Other sections can go here, such as search and directory-->
</div>
</header></pre>
<pre class="language-sass" data-tab="scss">//- DS2 core (c) 2024 Alexander McIlwraith
//- Licensed under CC BY-SA 4.0
$header-bg-color: var(--colour-grey-xxl) !default;
$font-heading: sans-serif !default;
$font-weight: 700 !default;
@mixin header {
header {
display: grid;
grid-template-rows: 1.75rem 3.5rem;
grid-column: 2 / 4;
overflow: hidden;
svg {
grid-column: 1 / -1;
grid-row: 1 / -1;
place-self: stretch;
text {
transform: translate(-1rem, 7.25rem);
font-size: 10rem;
font-weight: 1000;
font-family: $font-heading;
fill: $header-bg-color;
}
}
> div {
grid-row: 2;
grid-column: 1 / -1;
display: grid;
grid-column-gap: 1rem;
grid-template-columns: auto max-content max-content;
.header-title {
h1 {
margin: 0;
padding: 0 1rem;
a, a:visited {
border-bottom: none;
color: var(--colour-black);
font-family: $font-heading;
font-size: 2.5rem;
font-size: 32px;
font-weight: $font-weight;
margin: 0;
padding: 0;
text-decoration: none;
}
}
}
}
}
}</pre>
<pre class="language-css" data-tab="css">header {
display: -ms-grid;
display: grid;
-ms-grid-rows: 1.75rem 3.5rem;
grid-template-rows: 1.75rem 3.5rem;
-ms-grid-column: 2;
-ms-grid-column-span: 2;
grid-column: 2/4;
overflow: hidden;
}
header svg {
grid-column: 1/-1;
grid-row: 1/-1;
-ms-grid-row-align: stretch;
-ms-grid-column-align: stretch;
place-self: stretch;
}
header svg text {
-webkit-transform: translate(-1rem, 7.25rem);
-ms-transform: translate(-1rem, 7.25rem);
transform: translate(-1rem, 7.25rem);
font-size: 10rem;
font-weight: 1000;
font-family: sans-serif;
fill: var(--colour-grey-xxl);
}
header > div {
-ms-grid-row: 2;
grid-row: 2;
grid-column: 1/-1;
display: -ms-grid;
display: grid;
grid-column-gap: 1rem;
-ms-grid-columns: auto -webkit-max-content -webkit-max-content;
-ms-grid-columns: auto max-content max-content;
grid-template-columns: auto -webkit-max-content -webkit-max-content;
grid-template-columns: auto max-content max-content;
}
header > div .header-title h1 {
margin: 0;
padding: 0 1rem;
}
header > div .header-title h1 a, header > div .header-title h1 a:visited {
border-bottom: none;
color: var(--colour-black);
font-family: sans-serif;
font-size: 2.5rem;
font-size: 32px;
font-weight: 700;
margin: 0;
padding: 0;
text-decoration: none;
}</pre>
</div>
</body>
</html>

View File

@ -1,202 +0,0 @@
<html>
<head>
<title>Pattern</title>
</head>
<body data-prismjs-copy-timeout="1500">
<h2>What is it</h2>
<h2>When to use it</h2>
<h2>How to use it</h2>
<p>The tabbed user interface enables users to jump to their target section quickly. Tabs present like logically group information on the same page. Information should </p>
<ul>
<li>be logically chunked and ordered</li>
<li>be arallel in nature</li>
<li>show user's context</li>
<li>obvious where they begin and end </li>
</ul>
<p>Users should not need to see content of multiple tabs simultaneously and the user should be able to easily recognise where they are within the content. </p>
<p>The tab module can be initialised by importing a file with the javascript module using import * as tabs from "../pg/patterns/layouts/tabs/_tabs.js"; contains a modularized version of the jQuery code, so that it can be called on demand. It is what is used in the design system so that the JavaScript can be called at run time (after loading content).</p>
<tabset id="tabs">
<pre class="language-html" tab="html">
<div class="tab-group" id="uniqueID">
<div data-tab="[tab title]"></div>
<div data-tab="[tab title]"></div>
</div></pre>
<pre class="language-css" tab="css">tabset, .tab-group {
margin: 2rem 0 1rem 0;
}
tabset > ul, .tab-group > ul {
display: -webkit-box;
display: -ms-flexbox;
display: flex;
margin: 0;
padding: 0;
}
tabset > ul li.separator, .tab-group > ul li.separator {
border-bottom: 1px solid var(--colour-grey);
border-left: 1px solid var(--colour-grey);
display: inline-block;
margin: 0.45rem 0 0 0;
width: 100%;
}
tabset .tab-hidden, .tab-group .tab-hidden {
display: none;
}
tabset [role=tab], .tab-group [role=tab] {
background-color: var(--colour-white);
border-left: 1px solid var(--colour-grey);
border-top: 1px solid var(--colour-grey);
border-radius: 0.5rem 0.5rem 0 0;
cursor: pointer;
margin: 0;
display: inline;
padding: 1rem 1.5rem 0.14rem 1.5rem;
z-index: 2;
}
tabset [role=tab]:last-of-type, .tab-group [role=tab]:last-of-type {
border-right: 1px solid var(--colour-grey);
}
tabset [role=tab]:not(.selected), .tab-group [role=tab]:not(.selected) {
background-color: var(--colour-grey-xxl);
border-bottom: 1px solid var(--colour-grey);
}
tabset [role=tab] span, .tab-group [role=tab] span {
display: block;
margin: 0 0 0.5rem 0;
}
tabset [role=tabpanel], .tab-group [role=tabpanel] {
background-color: var(--colour-white);
border: 1px solid var(--colour-grey);
border-top: none;
padding: 1rem;
z-index: 1;
}
tabset [role=tabpanel]:not(.open), .tab-group [role=tabpanel]:not(.open) {
display: none;
}</pre>
<pre class="language-css" tab="scss">// DS2 core (c) 2024 Alexander McIlwraith
// Licensed under CC BY-SA 4.0
$tab-border: var(--colour-grey) !default;
$tab-selected: var(--colour-white) !default;
$tab-notselected: var(--colour-grey-xxl) !default;
@mixin tabs {
tabset, .tab-group {
margin: 2rem 0 1rem 0;
> ul {
display: flex;
margin: 0;
padding: 0;
li.separator {
border-bottom: 1px solid $tab-border;
border-left: 1px solid $tab-border;
display: inline-block;
margin: .45rem 0 0 0;
width: 100%;
}
}
.tab-hidden {
display: none;
}
[role="tab"] {
background-color: $tab-selected;
border-left: 1px solid $tab-border;
border-top: 1px solid $tab-border;
border-radius: .5rem .5rem 0 0;
cursor:pointer;
margin: 0;
display: inline;
padding: 1rem 1.5rem .14rem 1.5rem;
z-index: 2;
&:last-of-type {
border-right: 1px solid $tab-border;
}
&:not(.selected) {
background-color: $tab-notselected;
border-bottom: 1px solid $tab-border;
}
span {
display: block;
margin: 0 0 .5rem 0;
}
}
[role="tabpanel"] {
background-color: $tab-selected;
border: 1px solid $tab-border;
border-top: none;
padding: 1rem;
z-index: 1;
&:not(.open) {
display: none;
}
@content;
}
}
}</pre>
<pre class="language-css" tab="js">/* DS2 core (c) 2024 Alexander McIlwraith
import * as tabs from "../pg/patterns/layouts/tabs/_tabs.js";
tabs.init();
*/
export function init(p = document) {
p.querySelectorAll(".tab-group, tabset").forEach(tabGroup => {
if (tabGroup.querySelector("[role=tablist]") === null) {
const tabgroup = tabGroup.getAttribute("id");
let tablist = "";
Array.from(tabGroup.children).forEach(child => {
const tab = child.getAttribute("tab") || child.getAttribute("data-tab");
if (tab !== null) {
const tabID = tab.replace(/\W+/g, "-").toLowerCase();
const tabPanel = document.createElement('div');
tabPanel.id = `tab-panel-${tabgroup}-${tabID}`;
tabPanel.className = tablist === "" ? "open" : "";
tabPanel.setAttribute("role", "tabpanel");
tabPanel.setAttribute("tabindex", "0");
tabPanel.setAttribute("aria-labelledby", `tab-${tabgroup}-${tabID}`);
tabPanel.appendChild(child.cloneNode(true));
child.parentNode.replaceChild(tabPanel, child);
tablist += `<li tabindex="0" role="tab" ${tablist === "" ? "class='selected'" : ""} id="tab-${tabgroup}-${tabID}"><span>${tab}</span></li>`;
} else {
child.classList.add("tab-hidden");
}
});
const ul = document.createElement('ul');
ul.setAttribute("role", "tablist");
ul.innerHTML = `${tablist}<li role="separator" class="separator"></li>`;
tabGroup.insertBefore(ul, tabGroup.firstChild);
tabGroup.querySelectorAll('[role="tab"]').forEach(tab => {
tab.addEventListener("click", () => {
const siblings = Array.from(tab.parentNode.children);
siblings.forEach(sibling => sibling.classList.remove("selected"));
tab.classList.add("selected");
const tabPanels = Array.from(tab.parentNode.parentNode.children)
.filter(child => child.getAttribute("role") === "tabpanel");
tabPanels.forEach(panel => panel.classList.remove("open"));
const tabPanelId = tab.getAttribute("id").replace("tab", "tab-panel");
document.getElementById(tabPanelId).classList.add("open");
});
});
}
});
}
</pre>
</tabset>
</body>
</html>

View File

@ -12,7 +12,7 @@
<td colspan="2">This pattern doesn't exist (1)</td>
</tr>
<tr>
<td><a href="./?p=this-pattern-doesn't-exist"> This pattern doesn't exist</a></td>
<td><a href="./?p=this pattern doesn't exist"> This pattern doesn't exist</a></td>
<td><span class="status-deprecated">Deprecated</span></td>
</tr>
<tr>
@ -30,15 +30,15 @@
<td><span class="status-complete">Complete</span></td>
<tr>
<td><a href="./?p=components/sticky-note"> Sticky note</a></td>
<td><span class="status-in-progress">In progress</span></td>
<td><span class="status-complete">Complete</span></td>
</tr>
<tr>
<td><a href="./?p=components/switch"> Switch</a></td>
<td><span class="status-in-progress">In progress</span></td>
<td><span class="status-complete">Complete</span></td>
</tr>
<tr>
<td><a href="./?p=components/tooltip"> Tooltip</a></td>
<td><span class="status-in-progress">In progress</span></td>
<td><span class="status-complete">Complete</span></td>
</tr>
</tr>
<tr>
@ -49,11 +49,11 @@
<td><span class="status-complete">Complete</span></td>
<tr>
<td><a href="./?p=layouts/header"> Header</a></td>
<td><span class="status-in-progress">In progress</span></td>
<td><span class="status-complete">Complete</span></td>
</tr>
<tr>
<td><a href="./?p=layouts/breakpoints"> Breakpoints</a></td>
<td><span class="status-in-progress">In progress</span></td>
<td><span class="status-complete">Complete</span></td>
</tr>
<tr>
<td><a href="./?p=layouts/tabs"> Tabs</a></td>
@ -77,31 +77,15 @@
<td colspan="2"><span class="status-not-started">Not started (0)</span></td>
</tr>
<tr>
<td colspan="2"><span class="status-in-progress">In progress (5)</span></td>
<td colspan="2"><span class="status-in-progress">In progress (0)</span></td>
</tr>
<tr>
<td colspan="2"><span class="status-complete">Complete (10)</span></td>
</tr>
<tr>
<td> <a href="./?p=layouts/breakpoints">Breakpoints</a></td>
<td>Layouts</td>
</tr>
<tr>
<td> <a href="./?p=layouts/header">Header</a></td>
<td>Layouts</td>
</tr>
<tr>
<td> <a href="./?p=components/sticky-note">Sticky note</a></td>
<td>Components</td>
</tr>
<tr>
<td> <a href="./?p=components/switch">Switch</a></td>
<td>Components</td>
</tr>
<tr>
<td> <a href="./?p=components/tooltip">Tooltip</a></td>
<td>Components</td>
</tr>
<tr>
<td colspan="2"><span class="status-complete">Complete (5)</span></td>
</tr>
<tr>
<td> <a href="./?p=colours">Colours</a></td>
<td></td>
@ -110,6 +94,10 @@
<td> <a href="./?p=components">Components</a></td>
<td></td>
</tr>
<tr>
<td> <a href="./?p=layouts/header">Header</a></td>
<td>Layouts</td>
</tr>
<tr>
<td> <a href="./?p=layouts">Layouts</a></td>
<td></td>
@ -118,15 +106,27 @@
<td> <a href="./?p=status">Status</a></td>
<td></td>
</tr>
<tr>
<td> <a href="./?p=components/sticky-note">Sticky note</a></td>
<td>Components</td>
</tr>
<tr>
<td> <a href="./?p=components/switch">Switch</a></td>
<td>Components</td>
</tr>
<tr>
<td> <a href="./?p=layouts/tabs">Tabs</a></td>
<td>Layouts</td>
</tr>
<tr>
<td> <a href="./?p=components/tooltip">Tooltip</a></td>
<td>Components</td>
</tr>
<tr>
<td colspan="2"><span class="status-deprecated">Deprecated (1)</span></td>
</tr>
<tr>
<td> <a href="./?p=this-pattern-doesn't-exist">This pattern doesn't exist</a></td>
<td> <a href="./?p=this pattern doesn't exist">This pattern doesn't exist</a></td>
<td></td>
</tr>
</tbody>
@ -137,7 +137,7 @@
<tbody>
<tr>
<td> <a href="./?p=layouts/breakpoints">Breakpoints</a></td>
<td><span><span class="status-in-progress">In Progress</span></span></td>
<td><span><span class="status-complete">Complete</span></span></td>
<td>Layouts</td>
</tr>
<tr>
@ -152,7 +152,7 @@
</tr>
<tr>
<td> <a href="./?p=layouts/header">Header</a></td>
<td><span><span class="status-in-progress">In Progress</span></span></td>
<td><span><span class="status-complete">Complete</span></span></td>
<td>Layouts</td>
</tr>
<tr>
@ -167,12 +167,12 @@
</tr>
<tr>
<td> <a href="./?p=components/sticky-note">Sticky note</a></td>
<td><span><span class="status-in-progress">In Progress</span></span></td>
<td><span><span class="status-complete">Complete</span></span></td>
<td>Components</td>
</tr>
<tr>
<td> <a href="./?p=components/switch">Switch</a></td>
<td><span><span class="status-in-progress">In Progress</span></span></td>
<td><span><span class="status-complete">Complete</span></span></td>
<td>Components</td>
</tr>
<tr>
@ -181,13 +181,13 @@
<td>Layouts</td>
</tr>
<tr>
<td> <a href="./?p=this-pattern-doesn't-exist">This pattern doesn't exist</a></td>
<td> <a href="./?p=this pattern doesn't exist">This pattern doesn't exist</a></td>
<td><span><span class="status-deprecated">Deprecated</span></span></td>
<td></td>
</tr>
<tr>
<td> <a href="./?p=components/tooltip">Tooltip</a></td>
<td><span><span class="status-in-progress">In Progress</span></span></td>
<td><span><span class="status-complete">Complete</span></span></td>
<td>Components</td>
</tr>
</tbody>

View File

@ -5,142 +5,27 @@
</head>
<body data-prismjs-copy-timeout="1500">
<h2>What is it</h2>
<p>Sticky notes provide a way to attach information. They are a DS2 core pattern for making notes. </p>
<h2>When to use it</h2>
<p>Use a sticky when you want to make a note without adding it to the content. </p>
<h2>How to use it</h2>
<p>Uses absolute positioning.
<sticky-note class="blue" float="right">This <strong>is</strong> a test</sticky-note>You might need to add relative positioning to it's container.
<p>Uses absolute positioning. Passing an optional element to the init function will initialise tabs within that element. You can move the position using either <code class="language-html inline">float="&#91; right | left &#93;"</code> or <code class="language-html inline">offset="&#91; top | left &#93;"</code>. Offset will take negative values in any web measurement unit.
<sticky-note class="blue" offset="-10rem 1rem">This <strong>is</strong> a sample sticky. You can drag it out of the way if you need to see the content under it.</sticky-note>
<sticky-note float="right">You will notice when you hover over the sticky, it shows a dot in the colour of the sticky in the position where the sticky note refers to (assuming you haven't dragged it and scrolled that location off the screen).</sticky-note>
</p>
<p>If you wish to create a custom element, that extends another HTML element, the native element has to be extended in customElements.define(). Custom elements that inherit native elements are also known as "type extension custom elements". </p>
<sticky-note>another one</sticky-note>
<p>If you wish to create a custom element, that extends another HTML element, the native element has to be extended in customElements.define(). Custom elements that inherit native elements are also known as "type extension custom elements". </p>
<div class="tab-group" id="sticky-note">
<pre class="language-css" data-tab="css"> @import url("https://fonts.googleapis.com/css2?family=Kalam:wght@300;400;700&display=swap");
sticky-note-wrapper {
-webkit-box-sizing: border-box;
box-sizing: border-box;
border: 1px solid transparent;
border-radius: 50%;
display: inline-block;
height: 0.5rem;
position: relative;
width: 0.5rem;
}
sticky-note-wrapper * {
-webkit-box-sizing: border-box;
box-sizing: border-box;
}
sticky-note-wrapper sticky-note {
cursor: -webkit-grab;
cursor: grab;
display: -ms-grid;
display: grid;
float: left;
font-size: 1rem;
height: 13rem;
left: 0;
place-items: stretch;
position: absolute;
top: 0;
width: 13rem;
z-index: 100;
}
sticky-note-wrapper sticky-note:active {
cursor: -webkit-grabbing;
cursor: grabbing;
-webkit-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
user-select: none;
}
sticky-note-wrapper sticky-note.right {
float: right;
}
sticky-note-wrapper sticky-note > div {
-ms-grid-row: 1;
grid-row: 1;
-ms-grid-column: 1;
grid-column: 1;
}
sticky-note-wrapper sticky-note > div:nth-child(1) {
background-color: rgba(0, 0, 0, 0.25);
-webkit-box-shadow: -2px 2px 15px 0 rgba(0, 0, 0, 0.5);
box-shadow: -2px 2px 15px 0 rgba(0, 0, 0, 0.5);
display: -ms-grid;
display: grid;
margin: 2rem 1rem 0.25rem 0.36rem;
width: calc(100% - 1rem);
}
sticky-note-wrapper sticky-note > div:nth-child(2) {
clip-path: url(#stickyClip);
display: -ms-grid;
display: grid;
font-family: "Kalam", cursive;
font-style: 1rem;
font-weight: 300;
line-height: 1.25rem;
padding: 1rem;
place-items: center;
text-align: center;
}
sticky-note-wrapper sticky-note > div:nth-child(2) > * {
font-family: "Kalam", cursive !important;
font-style: normal !important;
font-weight: 300 !important;
}
@media screen and (max-width: 1024px) {
sticky-note-wrapper sticky-note > div:nth-child(2) {
max-width: 13rem;
min-width: 13rem;
width: 1rem;
}
}
@media screen and (max-width: 768px) {
sticky-note-wrapper sticky-note > div:nth-child(2) {
font-size: 1.75rem;
max-width: 21rem;
min-height: 21rem;
}
}
@media screen and (max-width: 640px) {
sticky-note-wrapper sticky-note > div:nth-child(2) {
font-size: 2.5rem;
max-width: 26rem;
min-height: 26rem;
}
}
sticky-note-wrapper sticky-note > div:nth-child(2) {
background: -webkit-gradient(linear, left top, left bottom, from(#ffffdd), color-stop(2%, #ffffd3), color-stop(12%, #ffffd3), color-stop(75%, #ffffc9), to(#ffffba));
background: linear-gradient(180deg, #ffffdd 0%, #ffffd3 2%, #ffffd3 12%, #ffffc9 75%, #ffffba 100%);
}
sticky-note-wrapper sticky-note.blue > div:nth-child(2) {
background: -webkit-gradient(linear, left top, left bottom, from(#9dddec), color-stop(2%, #94daea), color-stop(12%, #94daea), color-stop(75%, #8bd7e8), to(#7fd3e6));
background: linear-gradient(180deg, #9dddec 0%, #94daea 2%, #94daea 12%, #8bd7e8 75%, #7fd3e6 100%);
}
sticky-note-wrapper sticky-note.pink > div:nth-child(2) {
background: -webkit-gradient(linear, left top, left bottom, from(#fa7c93), color-stop(2%, #fa728b), color-stop(12%, #fa728b), color-stop(75%, #fa6883), to(#f95977));
background: linear-gradient(180deg, #fa7c93 0%, #fa728b 2%, #fa728b 12%, #fa6883 75%, #f95977 100%);
}
sticky-note-wrapper sticky-note.green > div:nth-child(2) {
background: -webkit-gradient(linear, left top, left bottom, from(#c5fcc9), color-stop(2%, #bbfbc0), color-stop(12%, #bbfbc0), color-stop(75%, #b1fab7), to(#a3faaa));
background: linear-gradient(180deg, #c5fcc9 0%, #bbfbc0 2%, #bbfbc0 12%, #b1fab7 75%, #a3faaa 100%);
}
sticky-note-wrapper:has(sticky-note:hover) {
background-color: #ffffd3;
border: 1px solid black;
}
sticky-note-wrapper:has(sticky-note.yellow:hover) {
background-color: #ffffd3;
}
sticky-note-wrapper:has(sticky-note.blue:hover) {
background-color: #94daea;
}
sticky-note-wrapper:has(sticky-note.pink:hover) {
background-color: #fa728b;
}
sticky-note-wrapper:has(sticky-note.green:hover) {
background-color: #bbfbc0;
}</pre>
<pre class="language-css" data-tab="scss"> //- DS2 core (c) 2024 Alexander McIlwraith
<tabset id="sticky-note">
<pre class="language-html" tab="html">
<sticky-note class="blue" float="right">This <strong>is</strong> a sample sticky. You can drag it out of the way if you need to see the content under it.</sticky-note></pre>
<pre class="language-pug" tab="pug">sticky-note(float="right").blue This #[strong is] a sample sticky.
| You can drag it out of the way if you need to see the content under it.</pre>
<pre class="language-css" data-tab="css"> @import url("https://fonts.googleapis.com/css2?family=Kalam:wght@300;400;700&display=swap");sticky-note-wrapper{-webkit-box-sizing:border-box;box-sizing:border-box;border:1px solid transparent;border-radius:50%;display:inline-block;height:0.5rem;position:relative;width:0.5rem}sticky-note-wrapper *{-webkit-box-sizing:border-box;box-sizing:border-box}sticky-note-wrapper sticky-note{cursor:-webkit-grab;cursor:grab;display:-ms-grid;display:grid;float:left;font-size:1rem;height:13rem;left:0;place-items:stretch;position:absolute;top:0;width:13rem;z-index:100}sticky-note-wrapper sticky-note:active{cursor:-webkit-grabbing;cursor:grabbing;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}sticky-note-wrapper sticky-note.right{float:right}sticky-note-wrapper sticky-note>div{-ms-grid-row:1;grid-row:1;-ms-grid-column:1;grid-column:1}sticky-note-wrapper sticky-note>div:first-child{background-color:rgba(0,0,0,0.25);-webkit-box-shadow:-2px 2px 15px 0 rgba(0,0,0,0.5);box-shadow:-2px 2px 15px 0 rgba(0,0,0,0.5);display:-ms-grid;display:grid;margin:2rem 1rem 0.25rem 0.36rem;width:calc(100% - 1rem)}sticky-note-wrapper sticky-note>div:nth-child(2){clip-path:url(#stickyClip);display:-ms-grid;display:grid;font-family:"Kalam",cursive;font-style:1rem;font-weight:300;line-height:1.25rem;padding:1rem;place-items:center;text-align:center}sticky-note-wrapper sticky-note>div:nth-child(2)>*{font-family:"Kalam",cursive!important;font-style:normal!important;font-weight:300!important}@media screen and (max-width:1024px){sticky-note-wrapper sticky-note>div:nth-child(2){max-width:13rem;min-width:13rem;width:1rem}}@media screen and (max-width:768px){sticky-note-wrapper sticky-note>div:nth-child(2){font-size:1.75rem;max-width:21rem;min-height:21rem}}@media screen and (max-width:640px){sticky-note-wrapper sticky-note>div:nth-child(2){font-size:2.5rem;max-width:26rem;min-height:26rem}}sticky-note-wrapper sticky-note>div:nth-child(2){background:-webkit-gradient(linear,left top,left bottom,from(#ffffdd),color-stop(2%,#ffffd3),color-stop(12%,#ffffd3),color-stop(75%,#ffffc9),to(#ffffba));background:linear-gradient(180deg,#ffffdd 0%,#ffffd3 2%,#ffffd3 12%,#ffffc9 75%,#ffffba 100%)}sticky-note-wrapper sticky-note.blue>div:nth-child(2){background:-webkit-gradient(linear,left top,left bottom,from(#9dddec),color-stop(2%,#94daea),color-stop(12%,#94daea),color-stop(75%,#8bd7e8),to(#7fd3e6));background:linear-gradient(180deg,#9dddec 0%,#94daea 2%,#94daea 12%,#8bd7e8 75%,#7fd3e6 100%)}sticky-note-wrapper sticky-note.pink>div:nth-child(2){background:-webkit-gradient(linear,left top,left bottom,from(#fa7c93),color-stop(2%,#fa728b),color-stop(12%,#fa728b),color-stop(75%,#fa6883),to(#f95977));background:linear-gradient(180deg,#fa7c93 0%,#fa728b 2%,#fa728b 12%,#fa6883 75%,#f95977 100%)}sticky-note-wrapper sticky-note.green>div:nth-child(2){background:-webkit-gradient(linear,left top,left bottom,from(#c5fcc9),color-stop(2%,#bbfbc0),color-stop(12%,#bbfbc0),color-stop(75%,#b1fab7),to(#a3faaa));background:linear-gradient(180deg,#c5fcc9 0%,#bbfbc0 2%,#bbfbc0 12%,#b1fab7 75%,#a3faaa 100%)}sticky-note-wrapper:has(sticky-note:hover){background-color:#ffffd3;border:1px solid black}sticky-note-wrapper:has(sticky-note.yellow:hover){background-color:#ffffd3}sticky-note-wrapper:has(sticky-note.blue:hover){background-color:#94daea}sticky-note-wrapper:has(sticky-note.pink:hover){background-color:#fa728b}sticky-note-wrapper:has(sticky-note.green:hover){background-color:#bbfbc0}</pre>
<div tab="scss">
<pre class="language-sass">$sticky-colors: ( [sass map with your own defined colours] );
@import "scss/core/switch/_sticky-note";
@include sticky-note;
</pre>
<pre class="language-sass">//- DS2 core (c) 2024 Alexander McIlwraith
//- Licensed under CC BY-SA 4.0
@use 'sass:color';
@ -292,7 +177,12 @@ $sticky-colors: (
}
}
}</pre>
<pre class="language-js" data-tab="js"> //- DS2 core (c) 2024 Alexander McIlwraith
</div>
<div tab="js">
<pre class="language-js">import * as stickynote from ""./js/core/sticky-note/_sticky-note.js";
stickynote.init()
</pre>
<pre class="language-js">//- DS2 core (c) 2024 Alexander McIlwraith
//- Licensed under CC BY-SA 4.0
const font = {
@ -424,5 +314,6 @@ export function init(p = document){
}
}</pre>
</div>
</tabset>
</body>
</html>

View File

@ -0,0 +1,102 @@
<html>
<head>
<title>Pattern</title>
</head>
<body data-prismjs-copy-timeout="1500">
<h2>What is it</h2>
<p>Switches are used to toggle application state between two mutually exclusive values. </p>
<h2>When to use it</h2>
<p>Use a switch when the user will see an immediate visible state change. Do not use a switch when the state change will affect future results. The user should not have to perform another action (search, save, etc) for the result to take affect. If the change in state does not take effect immediately, consider a checkbox. </p>
<h2>How to use it</h2>
<p>The switch label should describe what will happen when the switch is turned to the on state. Frontload labels with keywords. </p>
<p>Include the CSS and JavaScript. An additional handler will need to be created for the actual state change. The CSS implements the visual design of the switch, which is based on the accessibility properties, which are implemented by the JavaScript.</p>
<h2>Example</h2>
<p class="switch">
<label for="example-switch">Switch label (states the on state)</label><span id="example-switch" role="switch"></span>
</p>
<div class="tab-group" id="switches">
<pre class="language-html" tab="html"><span id="example-id" role="switch"></span></pre>
<pre class="language-pug" tab="pug">span#example-id(role="switch")</pre>
<pre class="language-css" tab="css">[role=switch]{display:-ms-inline-grid;display:inline-grid;border:1px solid #2e51a1;background-color:#d8d8d8;border-radius:0.75rem;height:1.5rem;width:3rem;-webkit-transition:all 500ms;transition:all 500ms}[role=switch]>span{display:inline-block;background-color:white;border-radius:50%;margin:2%;width:calc(1.5rem - 2%);-webkit-transition:all 500ms;transition:all 500ms}[role=switch][aria-checked=true]{background-color:#2e51a1}[role=switch][aria-checked=true]>span{margin-left:calc(1.5rem - 5%)}</pre>
<div tab="scss">
<pre class="language-sass">@import "scss/core/switch/_switch";
@include switch;
</pre>
<pre class="language-sass">//- DS2 core (c) 2024 Alexander McIlwraith
//- Licensed under CC BY-SA 4.0
@use "sass:math";
$switch-accent: #2e51a1 !default; // switch background when switched right (on/ true)
$switch-background: #d8d8d8 !default; // switch background when switched left (off / false)
$switch-color: white !default; // the colour of the switch
$switch-height: 1.5rem !default;
@mixin switch {
[role='switch'] {
display: inline-grid;
border: 1px solid $switch-accent;
background-color: $switch-background;
border-radius: math.div($switch-height, 2);
height: $switch-height;
width: #{$switch-height * 2};
transition: all 500ms;
> span {
display: inline-block;
background-color: white;
border-radius: 50%;
margin: 2%;
width: calc(#{$switch-height} - 2%);
transition: all 500ms;
}
&[aria-checked="true"] {
background-color: $switch-accent;
> span {
margin-left: calc(#{$switch-height} - 5%);
}
}
}
}</pre>
</div>
<div tab="js">
<pre class="language-js">// Note that switch is a reserved word.
import * as swtch from "./js/core/switch/_switch.js";
swtch.init();
</pre>
<pre class="language-js">//- DS2 core (c) 2024 Alexander McIlwraith
//- Licensed under CC BY-SA 4.0
function flip(e) {
let sw = e.currentTarget;
switch(sw.getAttribute("aria-checked")) {
case "true":
sw.setAttribute("aria-checked", "false");
break;
case "false":
sw.setAttribute("aria-checked", "true");
break;
}
};
module.exports = {
init: (p = document) => {
try {
p.querySelectorAll("[role='switch']").forEach((sw) => {
sw.innerHTML = "<span></span>";
sw.setAttribute("aria-checked", "false");
sw.setAttribute("tabindex", "0");
sw.addEventListener("click", flip, false);
sw.addEventListener("keypress", flip, false);
})
} catch (e) {
console.warn("Cannot initialise switches.", e);
}
}
}
</pre>
</div>
</div>
</body>
</html>

View File

@ -0,0 +1,285 @@
<html>
<head>
<title>Pattern</title>
<script>
let u = document.location.href.substring(0, document.location.href.search(/patterns/i));
let p = document.location.pathname.substring(document.location.pathname.search(/patterns/i));
p = p.replace(/\/$|\/index\.html/i, "").substring(9);
window.location = u + "?p=" + p;
</script>
</head>
<body data-prismjs-copy-timeout="1500">
<h2>What is it</h2>
<p>A tabs component that provides different sections of content that are displayed one at a time when the user selects that information. </p>
<h2>When to use it</h2>
<p>The tabbed user interface enables users to jump to their target section quickly. Tabs present like logically group information on the same page. Information should </p>
<ul>
<li>be logically chunked and ordered</li>
<li>be arallel in nature</li>
<li>show user's context</li>
<li>obvious where they begin and end </li>
</ul>
<p>Users should not need to see content of multiple tabs simultaneously and the user should be able to easily recognise where they are within the content. </p>
<h2>How to use it</h2>
<p>The structure of the tab set is defined in html. There are two forms supported. Adding a class of <code class="inline">.tab-group</code> to the container element will work in place of the <code class="inline">tabset</code> tag, and the tab panels can be defined using either <code class="inline">tab=""</code> or <code class="inline">data-tab=""</code>. Passing an optional element to the init function will initialise tabs within that element. </p>
<p>The tab initalize function now takes a new function parameter in the form of an third argument is an object that can take the following callbacks: </p>
<ul>
<li>altModifer (When the altKey is used)</li>
<li>shiftModifier (When the shift key is used)</li>
<li>metaModifier (When the Windows key or Apple key is used)</li>
</ul>
<p>You can use these callbacks to create a custom event to get the tab information. </p>
<p>Note: There is a new core function (core.getTabPath) that will generate the query string and url hash for use in DS2 Core. You may wish to update your scaffolding.js file to make use of this functionality. </p>
<tabset id="tabs">
<pre class="language-html" tab="html">
<tabset id="uniqueID">
<div tab="[tab title]"></div>
<div tab="[tab title]"></div>
</tabset></pre>
<pre class="language-pug" tab="pug">tabset#uniqueID
div(tab="[tab title]")
div(tab="[tab title]")
</pre>
<pre class="language-css" tab="css">tabset, .tab-group {
margin: 2rem 0 1rem 0;
}
tabset > ul, .tab-group > ul {
display: -webkit-box;
display: -ms-flexbox;
display: flex;
margin: 0;
padding: 0;
}
tabset > ul li.separator, .tab-group > ul li.separator {
border-bottom: 1px solid #7f7f7f;
border-left: 1px solid #7f7f7f;
display: inline-block;
margin: 0.45rem 0 0 0;
width: 100%;
}
tabset .tab-hidden, .tab-group .tab-hidden {
display: none;
}
tabset [role=tab], .tab-group [role=tab] {
background-color: #FFF;
border-left: 1px solid #7f7f7f;
border-top: 1px solid #7f7f7f;
border-radius: 0.5rem 0.5rem 0 0;
cursor: pointer;
margin: 0;
display: inline;
padding: 1rem 1.5rem 0.14rem 1.5rem;
z-index: 2;
}
tabset [role=tab]:last-of-type, .tab-group [role=tab]:last-of-type {
border-right: 1px solid #7f7f7f;
}
tabset [role=tab]:not(.selected), .tab-group [role=tab]:not(.selected) {
background-color: #f0f0f0;
border-bottom: 1px solid #7f7f7f;
}
tabset [role=tab] span, .tab-group [role=tab] span {
display: block;
margin: 0 0 0.5rem 0;
}
tabset [role=tabpanel], .tab-group [role=tabpanel] {
background-color: #FFF;
border: 1px solid #7f7f7f;
border-top: none;
padding: 1rem;
z-index: 1;
}
tabset [role=tabpanel]:not(.open), .tab-group [role=tabpanel]:not(.open) {
display: none;
}</pre>
<div tab="scss">
<pre class="language-sass">@import "scss/core/tabs/_tabs";
@include tabs{
// optional content block
};
</pre>
<pre class="language-sass">// DS2 core (c) 2024 Alexander McIlwraith
// Licensed under CC BY-SA 4.0
$tab-border: #7f7f7f !default;
$tab-selected: #FFF !default;
$tab-notselected: #f0f0f0 !default;
@mixin tabs {
tabset, .tab-group {
margin: 2rem 0 1rem 0;
> ul {
display: flex;
margin: 0;
padding: 0;
li.separator {
border-bottom: 1px solid $tab-border;
border-left: 1px solid $tab-border;
display: inline-block;
margin: .45rem 0 0 0;
width: 100%;
}
}
.tab-hidden {
display: none;
}
[role="tab"] {
background-color: $tab-selected;
border-left: 1px solid $tab-border;
border-top: 1px solid $tab-border;
border-radius: .5rem .5rem 0 0;
cursor:pointer;
margin: 0;
display: inline;
padding: 1rem 1.5rem .14rem 1.5rem;
z-index: 2;
&:last-of-type {
border-right: 1px solid $tab-border;
}
&:not(.selected) {
background-color: $tab-notselected;
border-bottom: 1px solid $tab-border;
}
span {
display: block;
margin: 0 0 .5rem 0;
}
}
[role="tabpanel"] {
background-color: $tab-selected;
border: 1px solid $tab-border;
border-top: none;
padding: 1rem;
z-index: 1;
&:not(.open) {
display: none;
}
@content;
}
}
}</pre>
</div>
<div tab="js">
<pre class="language-js">import * as tabs from "./js/core/tabs/_tabs.js";
tabs.init();</pre>
<pre class="language-js">/* DS2 core (c) 2024 Alexander McIlwraith
Released under Creative Commons Attribution-ShareAlike 4.0 International
*/
// create a pure JS mouse click event
const click = new MouseEvent('click', {
view: window,
bubbles: false,
cancelable: true
});
const waitForElement = (selector) => {
return new Promise(resolve => {
if (document.querySelector(selector)) {
return resolve(document.querySelector(selector));
}
const observer = new MutationObserver(mutations => {
if (document.querySelector(selector)) {
observer.disconnect();
resolve(document.querySelector(selector));
}
});
// If you get "parameter 1 is not of type 'Node'" error, see https://stackoverflow.com/a/77855838/492336
observer.observe(document.body, {
childList: true,
subtree: true
});
});
}
export function init(container = document, spacer = true, args = {}) {
container.querySelectorAll(".tab-group, tabset").forEach(tabGroup => {
if (tabGroup.querySelector("[role=tablist]") === null) {
const tabgroup = tabGroup.getAttribute("id");
let tablist = "";
Array.from(tabGroup.children).forEach(child => {
const tab = child.getAttribute("tab") || child.getAttribute("data-tab");
if (tab !== null) {
const tabID = tab.replace(/\W+/g, "-").toLowerCase();
const tabPanel = document.createElement('div');
tabPanel.id = `tab-panel-${tabgroup}-${tabID}`;
tabPanel.className = tablist === "" ? "open" : "";
tabPanel.setAttribute("role", "tabpanel");
tabPanel.setAttribute("tabindex", "0");
tabPanel.setAttribute("aria-labelledby", `tab-${tabgroup}-${tabID}`);
tabPanel.appendChild(child.cloneNode(true));
child.parentNode.replaceChild(tabPanel, child);
tablist += `<li tabindex="0" role="tab" ${tablist === "" ? "class='selected'" : ""} id="tab-${tabgroup}-${tabID}"><span>${tab}</span></li>`;
} else {
child.classList.add("tab-hidden");
}
});
const ul = document.createElement('ul');
ul.setAttribute("role", "tablist");
ul.innerHTML = spacer != true ? `${tablist}` : `${tablist}<li role="separator" class="separator"></li>`;
tabGroup.insertBefore(ul, tabGroup.firstChild);
tabGroup.querySelectorAll('[role="tab"]').forEach(tab => {
tab.addEventListener("click", (e) => {
if (e.altKey && typeof args.altModifier == "function") {
args.altModifier(tab);
} else if (e.shiftKey && typeof args.shiftModifier == "function") {
args.shiftModifier(tab);
} else if (e.metaKey && typeof args.metaModifier == "function") {
args.metaModifier(tab);
} else {
const siblings = Array.from(tab.parentNode.children);
siblings.forEach(sibling => sibling.classList.remove("selected"));
tab.classList.add("selected");
const tabPanels = Array.from(tab.parentNode.parentNode.children)
.filter(child => child.getAttribute("role") === "tabpanel");
tabPanels.forEach(panel => panel.classList.remove("open"));
const tabPanelId = tab.getAttribute("id").replace("tab", "tab-panel");
document.getElementById(tabPanelId).classList.add("open");
}
});
tab.addEventListener("keypress", (e) => {
e.preventDefault();
if( e.which == 32 || e.which == 13 ) {
e.currentTarget.dispatchEvent(click);
}
})
});
}
if (document.location.hash != "" && document.location.hash.substring(0,5) == "#tab-") {
waitForElement(document.location.hash).then((el) => {
el.scrollIntoView();
el.dispatchEvent(click);
});
}
});
}
</pre>
</div>
</tabset>
</body>
</html>

View File

@ -0,0 +1,367 @@
<html>
<head>
<title>Pattern</title>
</head>
<body data-prismjs-copy-timeout="1500">
<h2>What is it</h2>
<p>Tooltips provide brief information messaging through a mouse or keyboard hover. </p>
<h2>When to use it</h2>
<p>Use tool tips to provide additional information. Don't use tooltips for that is required to complete an interaction as the information disappears when it loses the hover state. </p>
<p>Use tooltips to help differentiate between multiple, close, similar options. </p>
<h2>How to use it</h2>
<p class="notification-box info">Currently, there is no easy way to activate a hover without with pure CSS without using a keyboard or mouse. Level4 media queries aim to solve that.</p>
<p>Either form works.
<sticky-note class="blue">"Either form works": What are the two forms.</sticky-note>Place the <code class="language-html inline">tooltip</code> inside another element for the tooltip to be 'linked to that element.' A container element may need to be added for a single tag element, such as a input field.
</p>
<p>Tool tip positions are: </p>
<ul>
<li>top / block-start</li>
<li>right / inline-end</li>
<li>bottom / block-end</li>
<li>left / inline-start</li>
</ul>
<p><a href="#">Link with a tool tip<span role="tooltip" inert="inert" tip-position="right">Tool tip content</span></a></p>
<tabset id="tooltip">
<pre class="language-html" tab="html"><a href="#">Link with a tool tip<span role="tooltip" inert="inert" tip-position="right">Tool tip content</span></a></pre>
<pre class="language-pug" tab="pug">a(href="#") Link with a tool tip
span(role="tooltip" inert tip-position="right") Tool tip content</pre>
<pre class="language-css" tab="css">/* Position Options
- top / block-start
- right / inline-end
- bottom / block-end
- left / inline-start
*/
[role=tooltip] {
background: #fff;
border-radius: 0.5rem;
color: #000;
-webkit-filter: drop-shadow(0 3px 3px hsla(0, 0%, 0%, 0.15)) drop-shadow(0 12px 12px hsla(0, 0%, 0%, 0.15));
filter: drop-shadow(0 3px 3px hsla(0, 0%, 0%, 0.15)) drop-shadow(0 12px 12px hsla(0, 0%, 0%, 0.15));
font-size: 1rem;
font-weight: 400;
inline-size: -webkit-max-content;
inline-size: -moz-max-content;
inline-size: max-content;
line-height: initial;
margin: 0;
max-inline-size: 25rem;
opacity: 0;
padding: 0.75rem 1.5rem;
pointer-events: none;
position: absolute;
text-align: start;
-webkit-transform: translate(var(--tooltip-x, 0)) translateY(var(--tooltip-y, 0));
-ms-transform: translate(var(--tooltip-x, 0)) translateY(var(--tooltip-y, 0));
transform: translate(var(--tooltip-x, 0)) translateY(var(--tooltip-y, 0));
-webkit-transition: opacity 0.2s ease, -webkit-transform 0.2s ease;
transition: opacity 0.2s ease, -webkit-transform 0.2s ease;
transition: opacity 0.2s ease, transform 0.2s ease;
transition: opacity 0.2s ease, transform 0.2s ease, -webkit-transform 0.2s ease;
-webkit-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
user-select: none;
will-change: filter;
z-index: 10;
}
[role=tooltip]::before {
clip-path: inset(50%);
clip: rect(1px, 1px, 1px, 1px);
content: "; Has tooltip: ";
height: 1px;
margin: -1px;
overflow: hidden;
padding: 0;
position: absolute;
width: 1px;
}
[role=tooltip]::after {
background: #fff;
content: "";
inset: 0;
-webkit-mask: var(--tooltip-pointer);
mask: var(--tooltip-pointer);
position: absolute;
z-index: -1;
}
[role=tooltip]:is([tip-position=top],
[tip-position=block-start],
:not([tip-position]),
[tip-position=bottom],
[tip-position=block-end]) {
text-align: center;
}
[role=tooltip]:is([tip-position=top],
[tip-position=block-start],
:not([tip-position])) {
inset-inline-start: 50%;
inset-block-end: calc(100% + 0.75rem + 1rem);
--tooltip-x: calc(50% * -1);
}
[role=tooltip]:is([tip-position=top],
[tip-position=block-start],
:not([tip-position]))::after {
--tooltip-pointer: conic-gradient(from -30deg at bottom, rgba(0, 0, 0, 0), #000 1deg 60deg, rgba(0, 0, 0, 0) 61deg) bottom/100% 50% no-repeat;
inset-block-end: -1rem;
-webkit-border-after: 1rem solid transparent;
border-block-end: 1rem solid transparent;
}
[role=tooltip]:is([tip-position=right],
[tip-position=inline-end]) {
inset-inline-start: calc(100% + 1.5rem + 1rem);
inset-block-end: 50%;
--tooltip-y: 50%;
}
[role=tooltip]:is([tip-position=right],
[tip-position=inline-end])::after {
--tooltip-pointer: conic-gradient(from 60deg at left, rgba(0, 0, 0, 0), #000 1deg 60deg, rgba(0, 0, 0, 0) 61deg) left/50% 100% no-repeat;
inset-inline-start: -1rem;
-webkit-border-start: 1rem solid transparent;
border-inline-start: 1rem solid transparent;
}
[role=tooltip]:is([tip-position=bottom],
[tip-position=block-end]) {
inset-inline-start: 50%;
inset-block-start: calc(100% + 0.75rem + 1rem);
--tooltip-x: calc(50% * -1);
}
[role=tooltip]:is([tip-position=bottom],
[tip-position=block-end])::after {
--tooltip-pointer: conic-gradient(from 150deg at top, rgba(0, 0, 0, 0), #000 1deg 60deg, rgba(0, 0, 0, 0) 61deg) top/100% 50% no-repeat;
inset-block-start: -1rem;
-webkit-border-before: 1rem solid transparent;
border-block-start: 1rem solid transparent;
}
[role=tooltip]:is([tip-position=left],
[tip-position=inline-start]) {
inset-inline-end: calc(100% + 1.5rem + 1rem);
inset-block-end: 50%;
--tooltip-y: 50%;
}
[role=tooltip]:is([tip-position=left],
[tip-position=inline-start])::after {
--tooltip-pointer: conic-gradient(from -120deg at right, rgba(0, 0, 0, 0), #000 1deg 60deg, rgba(0, 0, 0, 0) 61deg) right/50% 100% no-repeat;
inset-inline-end: -1rem;
-webkit-border-end: 1rem solid transparent;
border-inline-end: 1rem solid transparent;
}
@media (prefers-color-scheme: dark) {
[role=tooltip] {
background: #1f2127;
color: #fff;
-webkit-filter: drop-shadow(0 3px 3px hsla(0, 0%, 0%, 0.5)) drop-shadow(0 12px 12px hsla(0, 0%, 0%, 0.5));
filter: drop-shadow(0 3px 3px hsla(0, 0%, 0%, 0.5)) drop-shadow(0 12px 12px hsla(0, 0%, 0%, 0.5));
}
[role=tooltip]::after {
background: #1f2127;
}
}
:has(> [role=tooltip]) {
position: relative;
}
:has(> [role=tooltip]):is(:hover, :focus-visible, :active) > [role=tooltip] {
opacity: 1;
-webkit-transition-delay: 300ms;
transition-delay: 300ms;
}
@media (prefers-reduced-motion: no-preference) {
:has(> [role=tooltip]:is([tip-position=top], [tip-position=block-start], :not([tip-position]))):not(:hover):not(:active) [role=tooltip] {
--tooltip-y: 3px;
}
:has(> [role=tooltip]:is([tip-position=right], [tip-position=inline-end])):not(:hover):not(:active) [role=tooltip] {
--tooltip-x: calc(-1 * -3px * -1);
}
:has(> [role=tooltip]:is([tip-position=bottom], [tip-position=block-end])):not(:hover):not(:active) [role=tooltip] {
--tooltip-y: -3px;
}
:has(> [role=tooltip]:is([tip-position=left], [tip-position=inline-start])):not(:hover):not(:active) [role=tooltip] {
--tooltip-x: calc(-1 * 3px * -1);
}
}</pre>
<div tab="scss">
<pre class="language-sass">@import "scss/core/tooltip/_tooltip";
@include tooltip;</pre>
<pre class="language-sass">//- DS2 core (c) 2024 Alexander McIlwraith
//- Licensed under CC BY-SA 4.0
$tooltip-border-radius: .5rem !default;
$tooltip-dark-allow: true !default;
$tooltip-dark-background: #1f2127 !default;
$tooltip-dark-drop-shadow: drop-shadow(0 3px 3px hsl(0 0% 0% / 50%)) drop-shadow(0 12px 12px hsl(0 0% 0% / 50%)) !default;
$tooltip-dark-foreground: #fff !default;
$tooltip-light-background: #fff !default;
$tooltip-light-drop-shadow: drop-shadow(0 3px 3px hsl(0 0% 0% / 15%)) drop-shadow(0 12px 12px hsl(0 0% 0% / 15%)) !default;
$tooltip-light-foreground: #000 !default;
$tooltip-padding-sides: 1.5rem !default;
$tooltip-padding-top-bottom: 0.75rem !default;
$tooltip-pointer-size: 1rem !default;
$tooltip-pointer-bottom: conic-gradient(from -30deg at bottom, rgba(0, 0, 0, 0), #000 1deg 60deg, rgba(0, 0, 0, 0) 61deg) bottom / 100% 50% no-repeat !default;
$tooltip-pointer-left: conic-gradient(from 60deg at left, rgba(0, 0, 0, 0), #000 1deg 60deg, rgba(0, 0, 0, 0) 61deg) left / 50% 100% no-repeat !default;
$tooltip-pointer-right: conic-gradient(from -120deg at right, rgba(0, 0, 0, 0), #000 1deg 60deg, rgba(0, 0, 0, 0) 61deg) right / 50% 100% no-repeat !default;
$tooltip-pointer-top: conic-gradient(from 150deg at top, rgba(0, 0, 0, 0), #000 1deg 60deg, rgba(0, 0, 0, 0) 61deg) top / 100% 50% no-repeat !default;
/* Position Options
- top / block-start
- right / inline-end
- bottom / block-end
- left / inline-start
*/
@mixin tooltip {
[role="tooltip"] {
background: $tooltip-light-background;
border-radius: $tooltip-border-radius;
color: $tooltip-light-foreground;
filter: $tooltip-light-drop-shadow;
font-size: 1rem;
font-weight: 400;
inline-size: max-content;
line-height: initial;
margin: 0;
max-inline-size: 25rem;
opacity: 0;
padding: $tooltip-padding-top-bottom $tooltip-padding-sides;
pointer-events: none;
position: absolute;
text-align: start;
transform: translate(var(--tooltip-x, 0)) translateY(var(--tooltip-y, 0));
transition: opacity 0.2s ease, transform 0.2s ease;
user-select: none;
will-change: filter;
z-index: 10;
&::before {
clip-path: inset(50%);
clip: rect(1px, 1px, 1px, 1px);
content: "; Has tooltip: ";
height: 1px;
margin: -1px;
overflow: hidden;
padding: 0;
position: absolute;
width: 1px;
}
&::after {
background: $tooltip-light-background;
content: "";
inset: 0;
mask: var(--tooltip-pointer);
position: absolute;
z-index: -1;
}
&:is( [tip-position="top"],
[tip-position="block-start"],
:not([tip-position]),
[tip-position="bottom"],
[tip-position="block-end"]
) {
text-align: center;
}
&:is( [tip-position="top"],
[tip-position="block-start"],
:not([tip-position])
) {
inset-inline-start: 50%;
inset-block-end: calc(100% + $tooltip-padding-top-bottom + $tooltip-pointer-size);
--tooltip-x: calc(50% * -1);
&::after {
--tooltip-pointer: #{$tooltip-pointer-bottom};
inset-block-end: calc($tooltip-pointer-size * -1);
border-block-end: $tooltip-pointer-size solid transparent;
}
}
&:is( [tip-position="right"],
[tip-position="inline-end"]
) {
inset-inline-start: calc(100% + $tooltip-padding-sides + $tooltip-pointer-size);
inset-block-end: 50%;
--tooltip-y: 50%;
&::after {
--tooltip-pointer: #{$tooltip-pointer-left};
inset-inline-start: calc($tooltip-pointer-size * -1);
border-inline-start: $tooltip-pointer-size solid transparent;
}
}
&:is( [tip-position="bottom"],
[tip-position="block-end"]
) {
inset-inline-start: 50%;
inset-block-start: calc(100% + $tooltip-padding-top-bottom + $tooltip-pointer-size);
--tooltip-x: calc(50% * -1);
&::after {
--tooltip-pointer: #{$tooltip-pointer-top};
inset-block-start: calc($tooltip-pointer-size * -1);
border-block-start: $tooltip-pointer-size solid transparent;
}
}
&:is( [tip-position="left"],
[tip-position="inline-start"]
) {
inset-inline-end: calc(100% + $tooltip-padding-sides + $tooltip-pointer-size);
inset-block-end: 50%;
--tooltip-y: 50%;
&::after {
--tooltip-pointer: #{$tooltip-pointer-right};
inset-inline-end: calc($tooltip-pointer-size * -1);
-webkit-border-end: $tooltip-pointer-size solid transparent;
border-inline-end: $tooltip-pointer-size solid transparent;
}
}
@if ($tooltip-dark-allow == true ) {
@media (prefers-color-scheme: dark) {
background: $tooltip-dark-background;
color: $tooltip-dark-foreground;
filter: $tooltip-dark-drop-shadow;
&::after {
background: $tooltip-dark-background;
}
}
}
}
:has(> [role="tooltip"]) {
position: relative;
&:is(:hover, :focus-visible, :active) > [role="tooltip"] {
opacity: 1;
transition-delay: 300ms;
}
}
@media (prefers-reduced-motion: no-preference) {
:has(> [role="tooltip"]:is([tip-position="top"], [tip-position="block-start"], :not([tip-position]))):not(:hover):not(:active) [role="tooltip"] {
--tooltip-y: 3px;
}
:has(> [role="tooltip"]:is([tip-position="right"], [tip-position="inline-end"])):not(:hover):not(:active) [role="tooltip"] {
--tooltip-x: calc(-1 * -3px * -1);
}
:has(> [role="tooltip"]:is([tip-position="bottom"], [tip-position="block-end"])):not(:hover):not(:active) [role="tooltip"] {
--tooltip-y: -3px;
}
:has(> [role="tooltip"]:is([tip-position="left"], [tip-position="inline-start"])):not(:hover):not(:active) [role="tooltip"] {
--tooltip-x: calc(-1 * 3px * -1);
}
}
}</pre>
</div>
</tabset>
</body>
</html>

View File

@ -1,18 +1,27 @@
const getDate = function(){
var d = new Date();
return d.toLocaleDateString(lang, {day: "numeric", month: "long", year: "numeric"});
}
String.prototype.toTitleCase = function() {
return this.replace(/\w\S*/g, function(txt) {
return txt.charAt(0).toUpperCase() + txt.substr(1).toLowerCase();
});
}
String.prototype.toSentenceCase = function() {
return this.charAt(0).toUpperCase() + this.substr(1).toLowerCase();
}
String.prototype.toContent = function() {
return this.replace(/-/g, " ");
}
String.prototype.toPath = function() {
return this.trim().replace(/ /g, "_").replace(/-/g, "_").replace(/[\/\W]/g, "").replace(/_/g, "-");
}
const copyColourFallback = (copyInfo, attr) => {
const font = {
size: 0
}
const copyFallback = (copyInfo, attr) => {
console.log("fallback")
var textArea = document.createElement('textarea');
textArea.value = copyInfo;
@ -50,29 +59,16 @@ const copyColourFallback = (copyInfo, attr) => {
const showMessage = (m, s) => {
s = s == undefined ? true : s;
console.log("Copy success (navigator.clipboard)");
$("body").prepend("<div id='copystatus' style='display: none;'><div class='"+(s ? "succeeded" : "failed")+"'>" + m + "</div></div>");
$("#copystatus > div").css("top", (window.scrollY + 100)+ "px");
$("#copystatus").fadeIn(1000, function(){
$(this).fadeOut( 1000, function() {
$(this).remove();
});
})
}
let status = document.createElement("div");
status.setAttribute("id", "copystatus");
// status.style.display = "none";
status.innerHTML = "<div class='"+(s ? "succeeded" : "failed")+"'>" + m + "</div>";
document.querySelector("body").prepend(status)
const oneClickSelect = (e, t = e.currentTarget) => {
// In here, "this" is the element
var range, selection;
if (window.getSelection) {
selection = window.getSelection();
range = document.createRange();
range.selectNodeContents(t);
selection.removeAllRanges();
selection.addRange(range);
} else if (document.body.createTextRange) {
range = document.body.createTextRange();
range.moveToElementText(t);
range.select();
}
status.querySelector("div").style.top = (window.scrollY + 100)+ "px";
setTimeout( () => {
status.remove();
}, 1000);
}
const getURLVars = () => {
@ -90,7 +86,19 @@ const getURLVars = () => {
}
module.exports = {
url: getURLVars(),
url: (() => {
var v = {};
if (location.search.length > 0) {
var qs = (location.search.substr(1)).split("&");
for (var i = 0; i < qs.length; i++) {
var t = qs[i].split("=");
if (t[1].length > 0) {
v[t[0]] = decodeURIComponent(t[1].replace(/\+/g, '%20'));
}
}
}
return v;
})(),
cookie: {
set: (name, value, expires, path, domain, secure) => {
switch(typeof expires) {
@ -121,14 +129,26 @@ module.exports = {
}
return "";
},
remove: (cnane) => {
setCookie(cname, "", -1);
remove: (cname) => {
module.exports.cookie.set(cname, null, new Date(null));
},
},
oneClickSelect: (e, t = e.currentTarget) => {
// In here, "this" is the element
var range, selection;
if (window.getSelection) {
selection = window.getSelection();
range = document.createRange();
range.selectNodeContents(t);
selection.removeAllRanges();
selection.addRange(range);
} else if (document.body.createTextRange) {
range = document.body.createTextRange();
range.moveToElementText(t);
range.select();
}
},
colour: {
// showMessage: (m, s) => {
// showMessage(m, s);
// },
copy: (w, t) => {
let c = t.parentNode.getAttribute("data-" + (w=="var" ? "token" : w));
c = w == "var" ? `var(${c})` : c;
@ -137,52 +157,91 @@ module.exports = {
navigator.clipboard.writeText(c).then(function() {
showMessage(`Copied ${w}.`);
}, function(e) {
copyColourFallback(c,w);
copyFallback(c,w);
});
} else {
copyColourFallback(c, w);
copyFallback(c, w);
}
},
positionTooltip: () => {
$("color-pill > span").each(function(){
if ((Number($("p").css('font-size').replace("px","")) * 10) > $(this).offset().left) {
$(this).children("div.tooltip-tc").attr("tip-position", "right");
document.querySelectorAll("color-pill > span").forEach((ps) => {
ps.querySelectorAll("div.tooltip-tc").forEach((tip) => {
if ( (font.size * 10) > ps.offsetLeft ) {
tip.setAttribute("tip-position", "right");
} else {
$(this).children("div.tooltip-tc").attr("tip-position", "bottom");
tip.setAttribute("tip-position", "bottom");
}
});
})
}
},
getCSS: (el, prop, b = false) => {
return window.getComputedStyle(el, null).getPropertyValue(prop);
},
getTabPath: (t) => {
let url = window.location.toString();
url = url.indexOf("?") > 0 ? url.substring(0,url.indexOf("?")) : url;
url = `${url}?p=${t.closest("article").getAttribute("data-path")}#${t.getAttribute("id")}`
let type = "URL";
if (navigator.clipboard) {
navigator.clipboard.writeText(url).then(function() {
showMessage(`Copied ${type}.`);
}, function(e) {
copyFallback(url,type);
});
} else {
copyFallback(url, type);
}
},
init: (args = {}) => {
const url = getURLVars();
font.size = parseFloat(getComputedStyle(document.documentElement).fontSize.replace("px",""));
if (url.p !== undefined) {
document.querySelectorAll("main article:not([data-path^='" + url.p + "'])").forEach((a) => {
a.remove();
});
if (url.p == -1) {
document.querySelector("title").innerHTML = `${url.p.toContent().toTitleCase()} | ${$("title").attr("data-site")}`;
document.querySelector("title").innerHTML = `${url.p.toContent().toTitleCase()} | ${ document.querySelector("title").getAttribute("data-site") }`;
} else {
document.querySelector("title").innerHTML = `${url.p.substring(url.p.lastIndexOf("/")+1).toContent().toTitleCase()} | ${$("title").attr("data-site")}`
let theTitle = document.querySelectorAll("article");
if (theTitle.length > 0) {
theTitle = theTitle[0].getAttribute("data-name").toContent().toTitleCase();
if (document.querySelector("article").getAttribute("data-display") !== null) {
theTitle = document.querySelector("article").getAttribute("data-display")
}
document.querySelector("nav ul li a[href='./?p=" + (url.p.indexOf("/") == -1 ? url.p : url.p.substring(0, url.p.indexOf("/")) ) + "']").parentNode.classList.add("active");
} else {
document.querySelector("nav ul li a[href='./']").parentNode.classList.add("active");
document.querySelector("title").innerHTML = `${theTitle} | ${ document.querySelector("title").getAttribute("data-site") }`
}
}
}
if (typeof args.beforeArticleLoad == "function") args.beforeArticleLoad();
document.querySelectorAll("article").forEach((a) => {
if ( a.getAttribute("data-template") != "none" ) {
let path = "patterns/" + (a.getAttribute("data-core") == "true" ? "core/" : "") + a.getAttribute("data-path") + "/index.html";
const observer = new IntersectionObserver(articles => {
articles.forEach(article => {
let a = article.target;
if (article.isIntersecting == true) {
let path = a.getAttribute("data-path");
path = "patterns/" +
(a.getAttribute("data-core") == "true" ?
"core/" + path.substring(path.lastIndexOf("/") + 1) :
a.getAttribute("data-path"))
+ "/index.html";
const ASYNC = true;
let ajx = new XMLHttpRequest();
ajx.onreadystatechange = () => {
if (ajx.readyState == 4) {
observer.unobserve(article.target);
switch (ajx.status) {
case 200:
a.innerHTML = a.innerHTML + ajx.responseText;
a.style.height = "auto"
switch (a.getAttribute("data-template")) {
case "pug":
a.querySelectorAll("pre").forEach((aa) => {
@ -195,6 +254,7 @@ module.exports = {
})
break;
}
a.querySelectorAll("code").forEach((c)=> {
c.classList.add("line-numbers");
c.innerHTML = c.innerHTML.replace(/</g, "&lt;");
@ -206,7 +266,7 @@ module.exports = {
a.querySelectorAll("code").forEach((c)=> {
c.onclick = (e) => {
oneClickSelect(e);
module.exports.oneClickSelect(e);
}
})
@ -241,11 +301,27 @@ module.exports = {
default:
console.log("uncaught http error", { status: ajx.status, path: a.getAttribute("data-path") });
}
a.style.height = "auto";
if (typeof args.done == "function") args.done(a);
}
};
ajx.open("GET", path, ASYNC);
ajx.send();
}
})
}, { threshold: 0, rootMargin: "100%" })
observer.observe(a);
} else {
a.style.height = "auto";
}
})
if (typeof args.afterArticleLoad == "function") args.afterArticleLoad();
}
};

View File

@ -1,21 +1,23 @@
// core and prism
import * as core from './core/_core.js';
import * as Prism from "../../node_modules/prismjs/prism";
import "../../node_modules/prismjs/plugins/line-numbers/prism-line-numbers";
import "../../node_modules/prismjs/plugins/toolbar/prism-toolbar";
import '../../node_modules/prismjs/components/prism-json';
import '../../node_modules/prismjs/components/prism-pug';
import '../../node_modules/prismjs/components/prism-sass';
import "../../node_modules/prismjs/plugins/toolbar/prism-toolbar";
import "../../node_modules/prismjs/plugins/line-numbers/prism-line-numbers";
// import pattern stuff.
import * as swtch from "../pg/patterns/core/components/switch/_switch.js";
import * as stickynote from "../pg/patterns/core/components/sticky-note/_sticky-note.js";
import * as tabs from "../pg/patterns/core/layouts/tabs/_tabs.js";
import * as stickynote from "../pg/patterns/core/sticky-note/_sticky-note.js";
import * as swtch from "../pg/patterns/core/switch/_switch.js";
import * as tabs from "../pg/patterns/core/tabs/_tabs.js";
// init core
// init c
core.init({
success: (a) => {
tabs.init(a);
tabs.init(a, true, {
shiftModifier: core.getTabPath,
});
swtch.init(a);
stickynote.init(a);
},
@ -24,30 +26,52 @@ core.init({
}
});
jQuery(document).ready(function($){
// show deprecated switch
function flipDeprecated() {
setTimeout(function(){
if ($("#deprecated").attr("aria-checked") == "false") {
$(".status-deprecated").closest("article").addClass("status-deprecated");
core.cookie.set("show-deprecated", false, 30, "/");
} else {
$("article.status-deprecated").removeClass("status-deprecated");
core.cookie.set("show-deprecated", true, 30, "/");
}
}, 50);
}
$("#deprecated").on("click", flipDeprecated).on("keypress", flipDeprecated);
setTimeout( function() {
if (core.cookie.get("show-deprecated") == "true") {
$("#deprecated").attr("aria-checked", "true");
flipDeprecated();
// deprecated switch handler
const flipInfoSwitch = (e, s = e.currentTarget) => {
switch(s.getAttribute("id")) {
case "deprecated" :
core.cookie.set("show-deprecated", s.getAttribute("aria-checked"), 30, "/");
document.querySelector("main").querySelectorAll("article[data-status=deprecated]").forEach((a) => {
a.classList[( s.getAttribute("aria-checked") == "true" ? "add" : "remove" )]("show-deprecated");
});
break;
case "breakpoints" :
core.cookie.set("show-breakpoints", s.getAttribute("aria-checked"), 30, "/");
document.querySelector("html").classList[( s.getAttribute("aria-checked") == "true" ? "add" : "remove" )]("show-breakpoints");
break;
}
}, 200);
console.log("hide deprecated", { "type": (typeof core.cookie.get("show-deprecated")), "value": core.cookie.get("show-deprecated") });
// /hide deprecated switch
}
})
// create a pure JS mouse click event
const click = new MouseEvent('click', {
view: window,
bubbles: false,
cancelable: true
});
// import("../pg/patterns/layouts/main-navigation/_main-navigation.js");
// get the switch, initialize it and add the handler
let switches = document.querySelector(".info-switches");
swtch.init(switches);
let deprecated = document.querySelector("#deprecated");
let breakpoints = document.querySelector("#breakpoints");
deprecated.onclick = flipInfoSwitch;
deprecated.keypress = flipInfoSwitch;
breakpoints.onclick = flipInfoSwitch;
breakpoints.keypress = flipInfoSwitch;
// check a cookie to get the switch's state
if (core.cookie.get("show-deprecated") == "true") {
deprecated.dispatchEvent(click);
}
if (core.cookie.get("show-breakpoints") == "true") {
breakpoints.dispatchEvent(click);
}
// just for fun... We'll show deprecated if they match the path
// document.querySelector(`#${core.url.p.replace(/\//g, "-")}`).classList.add("show-deprecated");

View File

@ -7,7 +7,7 @@
-
var content = [
{
name: "this-pattern-doesn't-exist",
name: "this pattern doesn't exist",
status: "deprecated",
},
{
@ -22,17 +22,17 @@
files: [
{
name: "sticky-note",
status: "in-progress",
status: "complete",
core: true,
},
{
name: "switch",
status: "in-progress",
status: "complete",
core: true,
},
{
name: "tooltip",
status: "in-progress",
status: "complete",
core: true,
},
]
@ -45,12 +45,12 @@
files: [
{
name: "header",
status: "in-progress",
status: "complete",
core: true,
},
{
name: "breakpoints",
status: "in-progress",
status: "complete",
core: true,
},
{

View File

@ -128,24 +128,27 @@
- function generateCSS(c, p) {
- let o = "";
- for (let i = 0; i < c.length; i++) {
- o += `\n\t--${p}-${c[i].name.toLowerCase()}: ${ color(c[i].color, "hex").toLowerCase() },\n`;
- o += `\n\t--${p}-${c[i].name.toLowerCase()}: ${ color(c[i].color, "hex").toLowerCase() };\n`;
- for (let ii = 0; ii < c[i].grad.l.length; ii++) {
- o += `\t--${p}-${c[i].grad.l[ii].n.toLowerCase()}: ${ color(c[i].grad.l[ii].c, "hex").toLowerCase() },\n`;
- o += `\t--${p}-${c[i].grad.l[ii].n.toLowerCase()}: ${ color(c[i].grad.l[ii].c, "hex").toLowerCase() };\n`;
- }
- for (let ii = 0; ii < c[i].grad.d.length; ii++) {
- o += `\t--${p}-${c[i].grad.d[ii].n.toLowerCase()}: ${ color(c[i].grad.d[ii].c, "hex").toLowerCase() },\n`;
- o += `\t--${p}-${c[i].grad.d[ii].n.toLowerCase()}: ${ color(c[i].grad.d[ii].c, "hex").toLowerCase() };\n`;
- }
- }
- return o;
- }
if !colortxt
- var colortxt = "color"
mixin accessibility-info(c)
div.acchb
span color & black
span #{colortxt} & black
small= getContrastRatio(color(c, "rgb"), "rgb(0,0,0)") + ":1"
div.acchw
span color & white
span #{colortxt} & white
small= getContrastRatio(color(c, "rgb"), "rgb(255,255,255)") + ":1"
div.aa WCAG 2.0 AA
div.accbaa.result

View File

@ -1,7 +1,8 @@
include ../_config
block config
//-
DS2 core (c) 2024 Alexander McIlwraith
Core licensed under CC BY-SA 4.0
- var getDate = function(){
- const getDate = function(){
- var d = new Date();
- return d.toLocaleDateString(lang, {day: "numeric", month: "long", year: "numeric"});
- }
@ -16,23 +17,35 @@ block config
- String.prototype.toContent = function() {
- return this.replace(/-/g, " ");
- }
- String.prototype.toPath = function() {
- return this.trim().replace(/ /g, "_").replace(/-/g, "_").replace(/[\/\W]/g, "").replace(/_/g, "-");
- }
include ../_config
block config
mixin show-content(items, path)
- path = (path == "" ? "" : path + "/") + items.name
- if (items.status == "deprecated") {
- articlestatus = "status-deprecated"
- } else {
- articlestatus = ""
- }
article(id=path.replace(/\//g, "-")
class=articlestatus
data-path=path
data-template=(items.template == undefined ? "pug" : items.template)
data-pattern=items.name
- path = (path == "" ? "" : path + "/") + items.name.toPath()
if items.core == true
- items.status = "complete"
article(id=path.replace(/\//g, "-").toPath()
data-name=items.name
data-status=items.status
data-display=items.display
data-template=(items.template == undefined ? "pug" : items.template)
data-core= (items.core ? "true" : "false")
data-path=path
style="height: 100vh"
)
if items.display
h1(class="status-" + items.status )
span= items.display
tool-tip(role="tooltip" inert tip-position="right")= items.status.toSentenceCase().toContent()
else
h1(class="status-" + items.status )
span= items.name.toSentenceCase().toContent()
tool-tip(role="tooltip" inert tip-position="right")= items.status.toSentenceCase().toContent()
@ -52,9 +65,13 @@ html(lang= lang )
block head
link( href="assets/scaffolding.css" rel="stylesheet" )
script(src="assets/jquery-min.js")
body
//
DS2 core (c) 2024 Alexander McIlwraith
Core licensed under CC BY-SA 4.0
a.skip(href="#main") Skip to main content
div.container
@ -67,18 +84,3 @@ html(lang= lang )
+show-content(category, "")
script(src="assets/scaffolding-min.js")

View File

@ -1,11 +1,19 @@
//-
DS2 core (c) 2024 Alexander McIlwraith
Core licensed under CC BY-SA 4.0
include ../_config
block config
mixin h(h)
if headings[h]
if headings[h].indexOf("|") == -1
h2= headings[h]
else
- var cntnt = headings[h].split("|")
| <#{cntnt[0]}>#{cntnt[1]}</#{cntnt[0]}>
- var getDate = function(){
- const getDate = function(){
- var d = new Date();
- return d.toLocaleDateString(lang, {day: "numeric", month: "long", year: "numeric"});
- }
@ -20,12 +28,20 @@ mixin h(h)
- String.prototype.toContent = function() {
- return this.replace(/-/g, " ");
- }
- String.prototype.toPath = function() {
- return this.trim().replace(/ /g, "_").replace(/-/g, "_").replace(/[\/\W]/g, "").replace(/_/g, "-");
- }
html
head
title Pattern
script.
let u = document.location.href.substring(0, document.location.href.search(/patterns/i));
let p = document.location.pathname.substring(document.location.pathname.search(/patterns/i));
p = p.replace(/\/$|\/index\.html/i, "").substring(9);
window.location = u + "?p=" + p;
body(data-assetpath= assetpath data-prismjs-copy-timeout="1500")

View File

@ -75,7 +75,7 @@ include _colour-samples
"lighter lighter lighter darker darker darker"
"notes notes notes notes notes notes";
grid-template-columns: repeat(6, 1fr);
grid-template-rows: repeat(2, 1.5rem) 10rem repeat(3, max-content); // 3rem repeat(2, 2rem) 1.5rem repeat(3, max-content);
grid-template-rows: repeat(2, 1.5rem) repeat(4, max-content); // 3rem repeat(2, 2rem) 1.5rem repeat(3, max-content);
padding: 1rem;
width: 20rem;
max-width: 318px;
@ -115,7 +115,7 @@ include _colour-samples
display: grid;
gap: .5rem;
grid-template-columns: repeat(3, 1fr);
grid-template-rows: 2.5rem repeat(2, max-content);
grid-template-rows: repeat(3, max-content);
.result {
align-items: center;
border-radius: .5rem;
@ -188,7 +188,7 @@ include _colour-samples
padding: .5rem;
width: 20rem;
max-width: 318px;
height: 10.5rem;
height: max-contents;
display: grid;
gap: .5rem;
@ -231,6 +231,7 @@ include _colour-samples
display: block;
width: 100%;
place-self: stretch;
text-align: center;
span {
border: none;
font-size: .9rem;

View File

@ -8,17 +8,18 @@ block head
link(rel="icon" href="https://assets.gamv.ca/favicon-dark.svg" media="(prefers-color-scheme:dark)")
block header
include patterns/core/layouts/header/_header.pug
include patterns/core/header/_header.pug
nav
ul
li
a(href="./") Home
each first in content
li(class= navClass)
a(href="./?p=" + first.name )= first.name.toContent().toSentenceCase()
a(href="./?p=" + first.name.toPath() )= first.name.toContent().toSentenceCase()
p.deprecated-switch
p.info-switches
span
span#deprecated(role="switch")
label(for="deprecated") Show deprecated patterns
span
span#breakpoints(role="switch")
label(for="breakpoints") Show breakpoint information

View File

@ -1,7 +1,8 @@
//- DS2 core (c) 2024 Alexander McIlwraith
//- Licensed under CC BY-SA 4.0
$grid-breakpoints: ( xs: 0, sm: 576px, md: 768px, lg: 992px, xl: 1200px ) !default;
// default breakpoints match bootstrap 5 breakpoints.
$grid-breakpoints: ( xs: 0, sm: 576px, md: 768px, lg: 992px, xl: 1200px, xxl: 1400px ) !default;
@mixin breakpoint-debug {
body::before, body::after {
@ -9,6 +10,7 @@ $grid-breakpoints: ( xs: 0, sm: 576px, md: 768px, lg: 992px, xl: 1200px ) !defau
color: white;
content: "bigger than extra large";
display: grid;
font-family: sans-serif;
font-size: 25px;
grid-template-columns: auto;
padding: 25px;

View File

@ -0,0 +1,30 @@
//- DS2 core (c) 2024 Alexander McIlwraith
//- Core licensed under CC BY-SA 4.0
extends ../../../core/_master-pattern
block content
+h(0)
p Breakpoints enable responsive mobile design.
+h(1)
p Use breakpoints when designing for different screen sizes.
p The breakpoints SCSS mixin included implements media queries to allow for the change of the layout and design based on pre-defined screen sizes.
+h(2)
p This pattern is only available for SCSS breakpoints. The mixin is avai
p When using this, use the default break points as they are set to the same as the Bootstrap framework. The grid for the design system at large break point has been widened to accompdate 3 colour cards across.
tabset#breakpoints
div(tab="scss")
+h(3)
pre.language-sass.
@import "scss/core/breakpoints/breakpoints";
@include break([breakpoint]) {
// css here
}
+h(4)
pre.language-sass
include _breakpoints.scss

View File

@ -1,7 +1,20 @@
//- DS2 core (c) 2024 Alexander McIlwraith
//- Core licensed under CC BY-SA 4.0
extends ../../../core/_master-pattern
block content
+h(0)
p Colours are used to represent your site and are an implementation of your brand's visual identity.
+h(1)
p Colours are used throughout your patterns.
+h(2)
p Hover over the colour gradient sample pills to view the accessibility information for each colour sample against black and white.
p Click on the colour name or the colour gradient sample pills to copy the colour to your clipboard. A regular click will copy the hex code, a shift+click will copy the RGB code, the alt key (or Mac option&nbsp;&#8997; key) will copy the colour token, and the meta key (Windows key or Mac command&nbsp;&#8984; key) will copy a CSS colour var.
include ../../../core/_colour-samples
h2 Primary colours
h3 Primary colours
+colour-samples(colours, "colors")

View File

@ -1,24 +0,0 @@
extends ../../../../core/_master-pattern.pug
block content
+h(0)
+h(1)
+h(2)
p Uses absolute positioning.
sticky-note(float="right").blue This #[strong is] a test
| You might need to add relative positioning to it's container.
p If you wish to create a custom element, that extends another HTML element, the native element has to be extended in customElements.define(). Custom elements that inherit native elements are also known as "type extension custom elements".
sticky-note another one
p If you wish to create a custom element, that extends another HTML element, the native element has to be extended in customElements.define(). Custom elements that inherit native elements are also known as "type extension custom elements".
div#sticky-note.tab-group
pre.language-css(data-tab="css")
include sticky-note.css
pre.language-css(data-tab="scss")
include _sticky-note.scss
pre.language-js(data-tab="js")
include _sticky-note.js

View File

@ -1,126 +0,0 @@
@import url("https://fonts.googleapis.com/css2?family=Kalam:wght@300;400;700&display=swap");
sticky-note-wrapper {
-webkit-box-sizing: border-box;
box-sizing: border-box;
border: 1px solid transparent;
border-radius: 50%;
display: inline-block;
height: 0.5rem;
position: relative;
width: 0.5rem;
}
sticky-note-wrapper * {
-webkit-box-sizing: border-box;
box-sizing: border-box;
}
sticky-note-wrapper sticky-note {
cursor: -webkit-grab;
cursor: grab;
display: -ms-grid;
display: grid;
float: left;
font-size: 1rem;
height: 13rem;
left: 0;
place-items: stretch;
position: absolute;
top: 0;
width: 13rem;
z-index: 100;
}
sticky-note-wrapper sticky-note:active {
cursor: -webkit-grabbing;
cursor: grabbing;
-webkit-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
user-select: none;
}
sticky-note-wrapper sticky-note.right {
float: right;
}
sticky-note-wrapper sticky-note > div {
-ms-grid-row: 1;
grid-row: 1;
-ms-grid-column: 1;
grid-column: 1;
}
sticky-note-wrapper sticky-note > div:nth-child(1) {
background-color: rgba(0, 0, 0, 0.25);
-webkit-box-shadow: -2px 2px 15px 0 rgba(0, 0, 0, 0.5);
box-shadow: -2px 2px 15px 0 rgba(0, 0, 0, 0.5);
display: -ms-grid;
display: grid;
margin: 2rem 1rem 0.25rem 0.36rem;
width: calc(100% - 1rem);
}
sticky-note-wrapper sticky-note > div:nth-child(2) {
clip-path: url(#stickyClip);
display: -ms-grid;
display: grid;
font-family: "Kalam", cursive;
font-style: 1rem;
font-weight: 300;
line-height: 1.25rem;
padding: 1rem;
place-items: center;
text-align: center;
}
sticky-note-wrapper sticky-note > div:nth-child(2) > * {
font-family: "Kalam", cursive !important;
font-style: normal !important;
font-weight: 300 !important;
}
@media screen and (max-width: 1024px) {
sticky-note-wrapper sticky-note > div:nth-child(2) {
max-width: 13rem;
min-width: 13rem;
width: 1rem;
}
}
@media screen and (max-width: 768px) {
sticky-note-wrapper sticky-note > div:nth-child(2) {
font-size: 1.75rem;
max-width: 21rem;
min-height: 21rem;
}
}
@media screen and (max-width: 640px) {
sticky-note-wrapper sticky-note > div:nth-child(2) {
font-size: 2.5rem;
max-width: 26rem;
min-height: 26rem;
}
}
sticky-note-wrapper sticky-note > div:nth-child(2) {
background: -webkit-gradient(linear, left top, left bottom, from(#ffffdd), color-stop(2%, #ffffd3), color-stop(12%, #ffffd3), color-stop(75%, #ffffc9), to(#ffffba));
background: linear-gradient(180deg, #ffffdd 0%, #ffffd3 2%, #ffffd3 12%, #ffffc9 75%, #ffffba 100%);
}
sticky-note-wrapper sticky-note.blue > div:nth-child(2) {
background: -webkit-gradient(linear, left top, left bottom, from(#9dddec), color-stop(2%, #94daea), color-stop(12%, #94daea), color-stop(75%, #8bd7e8), to(#7fd3e6));
background: linear-gradient(180deg, #9dddec 0%, #94daea 2%, #94daea 12%, #8bd7e8 75%, #7fd3e6 100%);
}
sticky-note-wrapper sticky-note.pink > div:nth-child(2) {
background: -webkit-gradient(linear, left top, left bottom, from(#fa7c93), color-stop(2%, #fa728b), color-stop(12%, #fa728b), color-stop(75%, #fa6883), to(#f95977));
background: linear-gradient(180deg, #fa7c93 0%, #fa728b 2%, #fa728b 12%, #fa6883 75%, #f95977 100%);
}
sticky-note-wrapper sticky-note.green > div:nth-child(2) {
background: -webkit-gradient(linear, left top, left bottom, from(#c5fcc9), color-stop(2%, #bbfbc0), color-stop(12%, #bbfbc0), color-stop(75%, #b1fab7), to(#a3faaa));
background: linear-gradient(180deg, #c5fcc9 0%, #bbfbc0 2%, #bbfbc0 12%, #b1fab7 75%, #a3faaa 100%);
}
sticky-note-wrapper:has(sticky-note:hover) {
background-color: #ffffd3;
border: 1px solid black;
}
sticky-note-wrapper:has(sticky-note.yellow:hover) {
background-color: #ffffd3;
}
sticky-note-wrapper:has(sticky-note.blue:hover) {
background-color: #94daea;
}
sticky-note-wrapper:has(sticky-note.pink:hover) {
background-color: #fa728b;
}
sticky-note-wrapper:has(sticky-note.green:hover) {
background-color: #bbfbc0;
}

View File

@ -1,28 +0,0 @@
//- DS2 core (c) 2024 Alexander McIlwraith
//- Licensed under CC BY-SA 4.0
function flip(e) {
let sw = e.currentTarget;
switch(sw.getAttribute("aria-checked")) {
case "true":
sw.setAttribute("aria-checked", "false");
break;
case "false":
sw.setAttribute("aria-checked", "true");
break;
}
};
function init(callback){
let sw = document.querySelectorAll("[role='switch']");
for (let i=0; i < sw.length; i++) {
sw[i].innerHTML = "<span></span>";
sw[i].setAttribute("aria-checked", "false");
sw[i].setAttribute("tabindex", "0");
sw[i].addEventListener("click", flip, false);
sw[i].addEventListener("keypress", flip, false);
}
}
export {init};

View File

@ -1,25 +0,0 @@
extends ../../../../core/_master-pattern.pug
block content
+h(0)
+h(1)
+h(2)
h2 Example
p.switch
label(for="example-switch") Switch label
span#example-switch(role="switch")
div#switches.tab-group
pre.language-html(data-tab="html")
include _switch.pug
pre.language-pug(data-tab="pug")
include switch.pug
pre.language-css(data-tab="css")
include switch.css
pre.language-css(data-tab="scss")
include _switch.scss
pre.language-js(data-tab="js")
include _switch.js

View File

@ -1,26 +0,0 @@
[role=switch] {
display: -ms-inline-grid;
display: inline-grid;
border: 1px solid var(--colour-blue);
background-color: var(--colour-grey-xl);
border-radius: 0.75rem;
height: 1.5rem;
width: 3rem;
-webkit-transition: all 500ms;
transition: all 500ms;
}
[role=switch] > span {
display: inline-block;
background-color: white;
border-radius: 50%;
margin: 2%;
width: calc(1.5rem - 2%);
-webkit-transition: all 500ms;
transition: all 500ms;
}
[role=switch][aria-checked=true] {
background-color: var(--colour-blue);
}
[role=switch][aria-checked=true] > span {
margin-left: calc(1.5rem - 5%);
}

View File

@ -1,2 +0,0 @@
.
span#example-id(role="switch")

View File

@ -1,5 +0,0 @@
a(href="#") Link with a tool tip
div(role="tooltip" inert tip-position="bottom") Tool tip content
a(href="#") Link with a tool tip
tool-tip(role="tooltip" inert tip-position="bottom") Tool tip content

View File

@ -1,32 +0,0 @@
extends ../../../core/_master-pattern.pug
block content
+h(0)
+h(1)
+h(2)
p Either form works. Place this inside another element for the tooltip to be "linked to that element."
p Tool tip positions are:
ul
li top / block-start
li right / inline-end
li bottom / block-end
li left / inline-start
div#tooltip.tab-group
pre.language-html(data-tab="html")
include _tooltip.pug
pre.language-pug(data-tab="pug")
include tooltip.pug
pre.language-css(data-tab="css")
include tooltip.css
pre.language-css(data-tab="scss")
include _tooltip.scss

View File

@ -1,6 +0,0 @@
.
a(href="#") Link with a tool tip
div(role="tooltip" inert tip-position="bottom") Tool tip content
a(href="#") Link with a tool tip
tool-tip(role="tooltip" inert tip-position="bottom") Tool tip content

View File

@ -0,0 +1,16 @@
//- DS2 core (c) 2024 Alexander McIlwraith
//- Licensed under CC BY-SA 4.0
//- required variables
//- site - the site name that goes in the site title
//- root - the path to the root of the site
header
// The headline banner area
svg(height='5.5rem' width='100%' xmlns='http://www.w3.org/2000/svg' aria-hidden='true')
text= site
div
div.header-title
h1
a(href="./")= site
// Other sections can go here, such as search and directory

View File

@ -12,5 +12,5 @@ header
div
div.header-title
h1
a(href= root )= site
a(href="./")= site
// Other sections can go here, such as search and directory

View File

@ -0,0 +1 @@
header{display:-ms-grid;display:grid;-ms-grid-rows:1.75rem 3.5rem;grid-template-rows:1.75rem 3.5rem;-ms-grid-column:2;-ms-grid-column-span:2;grid-column:2/4;overflow:hidden}header svg{grid-column:1/-1;grid-row:1/-1;-ms-grid-row-align:stretch;-ms-grid-column-align:stretch;place-self:stretch}header svg text{-webkit-transform:translate(-1rem,7.25rem);-ms-transform:translate(-1rem,7.25rem);transform:translate(-1rem,7.25rem);font-size:10rem;font-weight:1000;font-family:sans-serif;fill:var(--colour-grey-xxl)}header>div{-ms-grid-row:2;grid-row:2;grid-column:1/-1;display:-ms-grid;display:grid;grid-column-gap:1rem;-ms-grid-columns:auto -webkit-max-content -webkit-max-content;-ms-grid-columns:auto max-content max-content;grid-template-columns:auto -webkit-max-content -webkit-max-content;grid-template-columns:auto max-content max-content}header>div .header-title h1{margin:0;padding:0 1rem}header>div .header-title h1 a,header>div .header-title h1 a:visited{border-bottom:none;color:var(--colour-black);font-family:sans-serif;font-size:2.5rem;font-size:32px;font-weight:700;margin:0;padding:0;text-decoration:none}

View File

@ -0,0 +1,38 @@
//- DS2 core (c) 2024 Alexander McIlwraith
//- Core licensed under CC BY-SA 4.0
extends ../../../core/_master-pattern
block content
+h(0)
p A header is layout pattern that helps the user identify the site.
+h(1)
p Use a header at the top of every page. The 'front page' of a site may have a different header than the rest of the pages.
+h(2)
p Place the header at the top of the page after the skip to main content link. You will likely want to replace core header should be replaced with your own site's header. To do this, remove the #[code.inline.language-js core: true ] and create your own pattern in the location you wish it in your design system.
tabset#header
pre.language-html(tab="html")
// create temp variables and store the design system values
- var tmpsite= site
- var tmproot= root
- site = "[site name]"
- root = "[site root]"
include _header.pug
//- reset variables to original values
- site= tmpsite
- root= tmproot
pre.language-pug(tab="pug")
include _header.pp
pre.language-css(tab="css")
include header.css
div.language-sass(tab="scss")
pre.language-sass.
@import "scss/core/header/header;
pre.language-sass
include _header.scss

View File

@ -1,13 +0,0 @@
extends ../../../../core/_master-pattern.pug
block content
+h(0)
+h(1)
+h(2)
p When using this, use the default break points as they are set to the same as the Bootstrap framework. The grid for the design system at large break point has been widened to accompdate 3 colour cards across.
div.tab-group#breakpoints
pre.language-css(data-tab="scss")
include _breakpoints.scss

View File

@ -1,53 +0,0 @@
header {
display: -ms-grid;
display: grid;
-ms-grid-rows: 1.75rem 3.5rem;
grid-template-rows: 1.75rem 3.5rem;
-ms-grid-column: 2;
-ms-grid-column-span: 2;
grid-column: 2/4;
overflow: hidden;
}
header svg {
grid-column: 1/-1;
grid-row: 1/-1;
-ms-grid-row-align: stretch;
-ms-grid-column-align: stretch;
place-self: stretch;
}
header svg text {
-webkit-transform: translate(-1rem, 7.25rem);
-ms-transform: translate(-1rem, 7.25rem);
transform: translate(-1rem, 7.25rem);
font-size: 10rem;
font-weight: 1000;
font-family: sans-serif;
fill: var(--colour-grey-xxl);
}
header > div {
-ms-grid-row: 2;
grid-row: 2;
grid-column: 1/-1;
display: -ms-grid;
display: grid;
grid-column-gap: 1rem;
-ms-grid-columns: auto -webkit-max-content -webkit-max-content;
-ms-grid-columns: auto max-content max-content;
grid-template-columns: auto -webkit-max-content -webkit-max-content;
grid-template-columns: auto max-content max-content;
}
header > div .header-title h1 {
margin: 0;
padding: 0 1rem;
}
header > div .header-title h1 a, header > div .header-title h1 a:visited {
border-bottom: none;
color: var(--colour-black);
font-family: sans-serif;
font-size: 2.5rem;
font-size: 32px;
font-weight: 700;
margin: 0;
padding: 0;
text-decoration: none;
}

View File

@ -1,23 +0,0 @@
extends ../../../../core/_master-pattern.pug
block content
div.tab-group#header
pre.language-html(data-tab="html")
// create temp variables and store the design system values
- var tmpsite= site
- var tmproot= root
- site = "[site name]"
- root = "[site root]"
include _header.pug
//- reset variables to original values
- site= tmpsite
- root= tmproot
pre.language-sass(data-tab="scss")
include _header.scss
pre.language-css(data-tab="css")
include header.css

View File

@ -1,53 +0,0 @@
/* DS2 core (c) 2024 Alexander McIlwraith
import * as tabs from "../pg/patterns/layouts/tabs/_tabs.js";
tabs.init();
*/
export function init(p = document) {
p.querySelectorAll(".tab-group, tabset").forEach(tabGroup => {
if (tabGroup.querySelector("[role=tablist]") === null) {
const tabgroup = tabGroup.getAttribute("id");
let tablist = "";
Array.from(tabGroup.children).forEach(child => {
const tab = child.getAttribute("tab") || child.getAttribute("data-tab");
if (tab !== null) {
const tabID = tab.replace(/\W+/g, "-").toLowerCase();
const tabPanel = document.createElement('div');
tabPanel.id = `tab-panel-${tabgroup}-${tabID}`;
tabPanel.className = tablist === "" ? "open" : "";
tabPanel.setAttribute("role", "tabpanel");
tabPanel.setAttribute("tabindex", "0");
tabPanel.setAttribute("aria-labelledby", `tab-${tabgroup}-${tabID}`);
tabPanel.appendChild(child.cloneNode(true));
child.parentNode.replaceChild(tabPanel, child);
tablist += `<li tabindex="0" role="tab" ${tablist === "" ? "class='selected'" : ""} id="tab-${tabgroup}-${tabID}"><span>${tab}</span></li>`;
} else {
child.classList.add("tab-hidden");
}
});
const ul = document.createElement('ul');
ul.setAttribute("role", "tablist");
ul.innerHTML = `${tablist}<li role="separator" class="separator"></li>`;
tabGroup.insertBefore(ul, tabGroup.firstChild);
tabGroup.querySelectorAll('[role="tab"]').forEach(tab => {
tab.addEventListener("click", () => {
const siblings = Array.from(tab.parentNode.children);
siblings.forEach(sibling => sibling.classList.remove("selected"));
tab.classList.add("selected");
const tabPanels = Array.from(tab.parentNode.parentNode.children)
.filter(child => child.getAttribute("role") === "tabpanel");
tabPanels.forEach(panel => panel.classList.remove("open"));
const tabPanelId = tab.getAttribute("id").replace("tab", "tab-panel");
document.getElementById(tabPanelId).classList.add("open");
});
});
}
});
}

View File

@ -1,4 +0,0 @@
div#uniqueID.tab-group
div(data-tab="[tab title]")
div(data-tab="[tab title]")

View File

@ -1,44 +0,0 @@
//- DS2 core (c) 2024 Alexander McIlwraith
//- Licensed under CC BY-SA 4.0
extends ../../../../core/_master-pattern.pug
block content
+h(0)
+h(1)
+h(2)
p The tabbed user interface enables users to jump to their target section quickly. Tabs present like logically group information on the same page. Information should
ul
li be logically chunked and ordered
li be arallel in nature
li show user's context
li obvious where they begin and end
p Users should not need to see content of multiple tabs simultaneously and the user should be able to easily recognise where they are within the content.
p The tab module can be initialised by importing a file with the javascript module using import * as tabs from "../pg/patterns/layouts/tabs/_tabs.js"; contains a modularized version of the jQuery code, so that it can be called on demand. It is what is used in the design system so that the JavaScript can be called at run time (after loading content).
tabset#tabs
pre.language-html(tab="html")
include _tabs.pug
//- pre.language-pug(tab="pug").
include _tabs.pug
pre.language-css(tab="css")
include tabs.css
pre.language-css(tab="scss")
include _tabs.scss
pre.language-css(tab="js")
include _tabs.js

View File

@ -1,26 +1,28 @@
extends ../../../core/_master-pattern.pug
//- DS2 core (c) 2024 Alexander McIlwraith
//- Core licensed under CC BY-SA 4.0
extends ../../../core/_master-pattern
block content
-
- let list = []
- for(let i = 0; i < content.length; i++) {
- list.push({ "name": content[i].name, "path": content[i].name, "status": content[i].status, "display": content[i].display } )
- list.push({ "name": content[i].name, "path": content[i].name, "status": content[i].status, "display": (content[i].hasOwnProperty("display") && content[i].display != "" ? content[i].display : content[i].name.toSentenceCase().toContent()) } )
- if (content[i].files != undefined) {
- for (let ii = 0; ii < content[i].files.length; ii++) {
- list.push({ "name": content[i].files[ii].name, "path": content[i].name +"."+ content[i].files[ii].name, "status": content[i].files[ii].status } )
- list.push({ "name": content[i].files[ii].name, "path": content[i].name +"."+ content[i].files[ii].name, "status": content[i].files[ii].status, "display": (content[i].files[ii].hasOwnProperty("display") && content[i].files[ii].display != "" ? content[i].files[ii].display : content[i].files[ii].name.toSentenceCase().toContent()) } )
- if (content[i].files[ii].files != undefined) {
- for (let iii = 0; iii < content[i].files[ii].files.length; iii++) {
- list.push({ "name": content[i].files[ii].files[iii].name, "path": content[i].name +"."+ content[i].files[ii].name + "." + content[i].files[ii].files[iii].name, "status": content[i].files[ii].files[iii].status } )
- list.push({ "name": content[i].files[ii].files[iii].name, "path": content[i].name +"."+ content[i].files[ii].name + "." + content[i].files[ii].files[iii].name, "status": content[i].files[ii].files[iii].status, "display": (content[i].files[ii].files[iii].hasOwnProperty("display") && content[i].files[ii].files[iii].display != "" ? content[i].files[ii].files[iii].display : content[i].files[ii].files[iii].name.toSentenceCase().toContent()) } )
- }
- }
- }
- }
- }
- list.sort((a, b) => {
- if (a.name < b.name) {
- if (a.display < b.display) {
- return -1;
- }
- if (a.name > b.name) {
- if (a.display > b.display) {
- return 1;
- }
- return 0;

View File

@ -0,0 +1,2 @@
sticky-note(float="right").blue This #[strong is] a sample sticky.
| You can drag it out of the way if you need to see the content under it.

View File

@ -0,0 +1,2 @@
sticky-note(float="right").blue This #[strong is] a sample sticky.
| You can drag it out of the way if you need to see the content under it.

View File

@ -0,0 +1,43 @@
//- DS2 core (c) 2024 Alexander McIlwraith
//- Core licensed under CC BY-SA 4.0
extends ../../../core/_master-pattern
block content
+h(0)
p Sticky notes provide a way to attach information. They are a DS2 core pattern for making notes.
+h(1)
p Use a sticky when you want to make a note without adding it to the content.
+h(2)
p Uses absolute positioning. Passing an optional element to the init function will initialise tabs within that element. You can move the position using either #[code.language-html.inline float="&#91; right | left &#93;"] or #[code.language-html.inline offset="&#91; top | left &#93;"]. Offset will take negative values in any web measurement unit.
sticky-note.blue(offset="-10rem 1rem") This #[strong is] a sample sticky. You can drag it out of the way if you need to see the content under it.
sticky-note(float="right") You will notice when you hover over the sticky, it shows a dot in the colour of the sticky in the position where the sticky note refers to (assuming you haven't dragged it and scrolled that location off the screen).
p If you wish to create a custom element, that extends another HTML element, the native element has to be extended in customElements.define(). Custom elements that inherit native elements are also known as "type extension custom elements".
tabset#sticky-note
pre.language-html(tab="html")
include _sticky-note.pug
pre.language-pug(tab="pug")
include _sticky-note.pp
pre.language-css(data-tab="css")
include sticky-note.css
div(tab="scss")
+h(3)
pre.language-sass.
$sticky-colors: ( [sass map with your own defined colours] );
@import "scss/core/switch/_sticky-note";
@include sticky-note;
+h(4)
pre.language-sass
include _sticky-note.scss
div(tab="js")
+h(3)
pre.language-js.
import * as stickynote from ""./js/core/sticky-note/_sticky-note.js";
stickynote.init()
+h(4)
pre.language-js
include _sticky-note.js

View File

@ -0,0 +1 @@
@import url("https://fonts.googleapis.com/css2?family=Kalam:wght@300;400;700&display=swap");sticky-note-wrapper{-webkit-box-sizing:border-box;box-sizing:border-box;border:1px solid transparent;border-radius:50%;display:inline-block;height:0.5rem;position:relative;width:0.5rem}sticky-note-wrapper *{-webkit-box-sizing:border-box;box-sizing:border-box}sticky-note-wrapper sticky-note{cursor:-webkit-grab;cursor:grab;display:-ms-grid;display:grid;float:left;font-size:1rem;height:13rem;left:0;place-items:stretch;position:absolute;top:0;width:13rem;z-index:100}sticky-note-wrapper sticky-note:active{cursor:-webkit-grabbing;cursor:grabbing;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}sticky-note-wrapper sticky-note.right{float:right}sticky-note-wrapper sticky-note>div{-ms-grid-row:1;grid-row:1;-ms-grid-column:1;grid-column:1}sticky-note-wrapper sticky-note>div:first-child{background-color:rgba(0,0,0,0.25);-webkit-box-shadow:-2px 2px 15px 0 rgba(0,0,0,0.5);box-shadow:-2px 2px 15px 0 rgba(0,0,0,0.5);display:-ms-grid;display:grid;margin:2rem 1rem 0.25rem 0.36rem;width:calc(100% - 1rem)}sticky-note-wrapper sticky-note>div:nth-child(2){clip-path:url(#stickyClip);display:-ms-grid;display:grid;font-family:"Kalam",cursive;font-style:1rem;font-weight:300;line-height:1.25rem;padding:1rem;place-items:center;text-align:center}sticky-note-wrapper sticky-note>div:nth-child(2)>*{font-family:"Kalam",cursive!important;font-style:normal!important;font-weight:300!important}@media screen and (max-width:1024px){sticky-note-wrapper sticky-note>div:nth-child(2){max-width:13rem;min-width:13rem;width:1rem}}@media screen and (max-width:768px){sticky-note-wrapper sticky-note>div:nth-child(2){font-size:1.75rem;max-width:21rem;min-height:21rem}}@media screen and (max-width:640px){sticky-note-wrapper sticky-note>div:nth-child(2){font-size:2.5rem;max-width:26rem;min-height:26rem}}sticky-note-wrapper sticky-note>div:nth-child(2){background:-webkit-gradient(linear,left top,left bottom,from(#ffffdd),color-stop(2%,#ffffd3),color-stop(12%,#ffffd3),color-stop(75%,#ffffc9),to(#ffffba));background:linear-gradient(180deg,#ffffdd 0%,#ffffd3 2%,#ffffd3 12%,#ffffc9 75%,#ffffba 100%)}sticky-note-wrapper sticky-note.blue>div:nth-child(2){background:-webkit-gradient(linear,left top,left bottom,from(#9dddec),color-stop(2%,#94daea),color-stop(12%,#94daea),color-stop(75%,#8bd7e8),to(#7fd3e6));background:linear-gradient(180deg,#9dddec 0%,#94daea 2%,#94daea 12%,#8bd7e8 75%,#7fd3e6 100%)}sticky-note-wrapper sticky-note.pink>div:nth-child(2){background:-webkit-gradient(linear,left top,left bottom,from(#fa7c93),color-stop(2%,#fa728b),color-stop(12%,#fa728b),color-stop(75%,#fa6883),to(#f95977));background:linear-gradient(180deg,#fa7c93 0%,#fa728b 2%,#fa728b 12%,#fa6883 75%,#f95977 100%)}sticky-note-wrapper sticky-note.green>div:nth-child(2){background:-webkit-gradient(linear,left top,left bottom,from(#c5fcc9),color-stop(2%,#bbfbc0),color-stop(12%,#bbfbc0),color-stop(75%,#b1fab7),to(#a3faaa));background:linear-gradient(180deg,#c5fcc9 0%,#bbfbc0 2%,#bbfbc0 12%,#b1fab7 75%,#a3faaa 100%)}sticky-note-wrapper:has(sticky-note:hover){background-color:#ffffd3;border:1px solid black}sticky-note-wrapper:has(sticky-note.yellow:hover){background-color:#ffffd3}sticky-note-wrapper:has(sticky-note.blue:hover){background-color:#94daea}sticky-note-wrapper:has(sticky-note.pink:hover){background-color:#fa728b}sticky-note-wrapper:has(sticky-note.green:hover){background-color:#bbfbc0}

View File

@ -0,0 +1,30 @@
//- DS2 core (c) 2024 Alexander McIlwraith
//- Licensed under CC BY-SA 4.0
function flip(e) {
let sw = e.currentTarget;
switch(sw.getAttribute("aria-checked")) {
case "true":
sw.setAttribute("aria-checked", "false");
break;
case "false":
sw.setAttribute("aria-checked", "true");
break;
}
};
module.exports = {
init: (p = document) => {
try {
p.querySelectorAll("[role='switch']").forEach((sw) => {
sw.innerHTML = "<span></span>";
sw.setAttribute("aria-checked", "false");
sw.setAttribute("tabindex", "0");
sw.addEventListener("click", flip, false);
sw.addEventListener("keypress", flip, false);
})
} catch (e) {
console.warn("Cannot initialise switches.", e);
}
}
}

View File

@ -0,0 +1 @@
span#example-id(role="switch")

View File

@ -3,9 +3,9 @@
@use "sass:math";
$switch-accent: var(--colour-blue) !default; // switch background when switched right (on/ true)
$switch-background: var(--colour-grey-xl) !default; // switch background when switched left (off / false)
$switch-color: var(--colour-white) !default; // the colour of the switch
$switch-accent: #2e51a1 !default; // switch background when switched right (on/ true)
$switch-background: #d8d8d8 !default; // switch background when switched left (off / false)
$switch-color: white !default; // the colour of the switch
$switch-height: 1.5rem !default;
@mixin switch {

View File

@ -0,0 +1,48 @@
//- DS2 core (c) 2024 Alexander McIlwraith
//- Core licensed under CC BY-SA 4.0
extends ../../../core/_master-pattern
block content
+h(0)
p Switches are used to toggle application state between two mutually exclusive values.
+h(1)
p Use a switch when the user will see an immediate visible state change. Do not use a switch when the state change will affect future results. The user should not have to perform another action (search, save, etc) for the result to take affect. If the change in state does not take effect immediately, consider a checkbox.
+h(2)
p The switch label should describe what will happen when the switch is turned to the on state. Frontload labels with keywords.
p Include the CSS and JavaScript. An additional handler will need to be created for the actual state change. The CSS implements the visual design of the switch, which is based on the accessibility properties, which are implemented by the JavaScript.
h2 Example
p.switch
label(for="example-switch") Switch label (states the on state)
span#example-switch(role="switch")
div#switches.tab-group
pre.language-html(tab="html")
include _switch.pug
pre.language-pug(tab="pug")
include _switch.pp
pre.language-css(tab="css")
include switch.css
div(tab="scss")
+h(3)
pre.language-sass.
@import "scss/core/switch/_switch";
@include switch;
+h(4)
pre.language-sass
include _switch.scss
div(tab="js")
+h(3)
pre.language-js.
// Note that switch is a reserved word.
import * as swtch from "./js/core/switch/_switch.js";
swtch.init();
+h(4)
pre.language-js
include _switch.js

View File

@ -0,0 +1 @@
[role=switch]{display:-ms-inline-grid;display:inline-grid;border:1px solid #2e51a1;background-color:#d8d8d8;border-radius:0.75rem;height:1.5rem;width:3rem;-webkit-transition:all 500ms;transition:all 500ms}[role=switch]>span{display:inline-block;background-color:white;border-radius:50%;margin:2%;width:calc(1.5rem - 2%);-webkit-transition:all 500ms;transition:all 500ms}[role=switch][aria-checked=true]{background-color:#2e51a1}[role=switch][aria-checked=true]>span{margin-left:calc(1.5rem - 5%)}

View File

@ -0,0 +1,105 @@
/* DS2 core (c) 2024 Alexander McIlwraith
Released under Creative Commons Attribution-ShareAlike 4.0 International
*/
// create a pure JS mouse click event
const click = new MouseEvent('click', {
view: window,
bubbles: false,
cancelable: true
});
const waitForElement = (selector) => {
return new Promise(resolve => {
if (document.querySelector(selector)) {
return resolve(document.querySelector(selector));
}
const observer = new MutationObserver(mutations => {
if (document.querySelector(selector)) {
observer.disconnect();
resolve(document.querySelector(selector));
}
});
// If you get "parameter 1 is not of type 'Node'" error, see https://stackoverflow.com/a/77855838/492336
observer.observe(document.body, {
childList: true,
subtree: true
});
});
}
export function init(container = document, spacer = true, args = {}) {
container.querySelectorAll(".tab-group, tabset").forEach(tabGroup => {
if (tabGroup.querySelector("[role=tablist]") === null) {
const tabgroup = tabGroup.getAttribute("id");
let tablist = "";
Array.from(tabGroup.children).forEach(child => {
const tab = child.getAttribute("tab") || child.getAttribute("data-tab");
if (tab !== null) {
const tabID = tab.replace(/\W+/g, "-").toLowerCase();
const tabPanel = document.createElement('div');
tabPanel.id = `tab-panel-${tabgroup}-${tabID}`;
tabPanel.className = tablist === "" ? "open" : "";
tabPanel.setAttribute("role", "tabpanel");
tabPanel.setAttribute("tabindex", "0");
tabPanel.setAttribute("aria-labelledby", `tab-${tabgroup}-${tabID}`);
tabPanel.appendChild(child.cloneNode(true));
child.parentNode.replaceChild(tabPanel, child);
tablist += `<li tabindex="0" role="tab" ${tablist === "" ? "class='selected'" : ""} id="tab-${tabgroup}-${tabID}"><span>${tab}</span></li>`;
} else {
child.classList.add("tab-hidden");
}
});
const ul = document.createElement('ul');
ul.setAttribute("role", "tablist");
ul.innerHTML = spacer != true ? `${tablist}` : `${tablist}<li role="separator" class="separator"></li>`;
tabGroup.insertBefore(ul, tabGroup.firstChild);
tabGroup.querySelectorAll('[role="tab"]').forEach(tab => {
tab.addEventListener("click", (e) => {
if (e.altKey && typeof args.altModifier == "function") {
args.altModifier(tab);
} else if (e.shiftKey && typeof args.shiftModifier == "function") {
args.shiftModifier(tab);
} else if (e.metaKey && typeof args.metaModifier == "function") {
args.metaModifier(tab);
} else {
const siblings = Array.from(tab.parentNode.children);
siblings.forEach(sibling => sibling.classList.remove("selected"));
tab.classList.add("selected");
const tabPanels = Array.from(tab.parentNode.parentNode.children)
.filter(child => child.getAttribute("role") === "tabpanel");
tabPanels.forEach(panel => panel.classList.remove("open"));
const tabPanelId = tab.getAttribute("id").replace("tab", "tab-panel");
document.getElementById(tabPanelId).classList.add("open");
}
});
tab.addEventListener("keypress", (e) => {
e.preventDefault();
if( e.which == 32 || e.which == 13 ) {
e.currentTarget.dispatchEvent(click);
}
})
});
}
if (document.location.hash != "" && document.location.hash.substring(0,5) == "#tab-") {
waitForElement(document.location.hash).then((el) => {
el.scrollIntoView();
el.dispatchEvent(click);
});
}
});
}

View File

@ -0,0 +1,4 @@
tabset#uniqueID
div(tab="[tab title]")
div(tab="[tab title]")

View File

@ -0,0 +1,4 @@
tabset#uniqueID
div(tab="[tab title]")
div(tab="[tab title]")

View File

@ -1,9 +1,9 @@
// DS2 core (c) 2024 Alexander McIlwraith
// Licensed under CC BY-SA 4.0
$tab-border: var(--colour-grey) !default;
$tab-selected: var(--colour-white) !default;
$tab-notselected: var(--colour-grey-xxl) !default;
$tab-border: #7f7f7f !default;
$tab-selected: #FFF !default;
$tab-notselected: #f0f0f0 !default;
@mixin tabs {
tabset, .tab-group {

View File

@ -0,0 +1,61 @@
//- DS2 core (c) 2024 Alexander McIlwraith
//- Core licensed under CC BY-SA 4.0
extends ../../../core/_master-pattern
block content
+h(0)
p A tabs component that provides different sections of content that are displayed one at a time when the user selects that information.
+h(1)
p The tabbed user interface enables users to jump to their target section quickly. Tabs present like logically group information on the same page. Information should
ul
li be logically chunked and ordered
li be arallel in nature
li show user's context
li obvious where they begin and end
p Users should not need to see content of multiple tabs simultaneously and the user should be able to easily recognise where they are within the content.
+h(2)
p The structure of the tab set is defined in html. There are two forms supported. Adding a class of #[code.inline .tab-group] to the container element will work in place of the #[code.inline tabset] tag, and the tab panels can be defined using either #[code.inline tab=""] or #[code.inline data-tab=""]. Passing an optional element to the init function will initialise tabs within that element.
p The tab initalize function now takes a new function parameter in the form of an third argument is an object that can take the following callbacks:
ul
li altModifer (When the altKey is used)
li shiftModifier (When the shift key is used)
li metaModifier (When the Windows key or Apple key is used)
p You can use these callbacks to create a custom event to get the tab information.
p Note: There is a new core function (core.getTabPath) that will generate the query string and url hash for use in DS2 Core. You may wish to update your scaffolding.js file to make use of this functionality.
tabset#tabs
pre.language-html(tab="html")
include _tabs.pug
pre.language-pug(tab="pug")
include _tabs.pp
pre.language-css(tab="css")
include tabs.css
div(tab="scss")
+h(3)
pre.language-sass.
@import "scss/core/tabs/_tabs";
@include tabs{
// optional content block
};
+h(4)
pre.language-sass
include _tabs.scss
div(tab="js")
+h(3)
pre.language-js.
import * as tabs from "./js/core/tabs/_tabs.js";
tabs.init();
+h(4)
pre.language-js
include _tabs.js

View File

@ -9,8 +9,8 @@ tabset > ul, .tab-group > ul {
padding: 0;
}
tabset > ul li.separator, .tab-group > ul li.separator {
border-bottom: 1px solid var(--colour-grey);
border-left: 1px solid var(--colour-grey);
border-bottom: 1px solid #7f7f7f;
border-left: 1px solid #7f7f7f;
display: inline-block;
margin: 0.45rem 0 0 0;
width: 100%;
@ -19,9 +19,9 @@ tabset .tab-hidden, .tab-group .tab-hidden {
display: none;
}
tabset [role=tab], .tab-group [role=tab] {
background-color: var(--colour-white);
border-left: 1px solid var(--colour-grey);
border-top: 1px solid var(--colour-grey);
background-color: #FFF;
border-left: 1px solid #7f7f7f;
border-top: 1px solid #7f7f7f;
border-radius: 0.5rem 0.5rem 0 0;
cursor: pointer;
margin: 0;
@ -30,19 +30,19 @@ tabset [role=tab], .tab-group [role=tab] {
z-index: 2;
}
tabset [role=tab]:last-of-type, .tab-group [role=tab]:last-of-type {
border-right: 1px solid var(--colour-grey);
border-right: 1px solid #7f7f7f;
}
tabset [role=tab]:not(.selected), .tab-group [role=tab]:not(.selected) {
background-color: var(--colour-grey-xxl);
border-bottom: 1px solid var(--colour-grey);
background-color: #f0f0f0;
border-bottom: 1px solid #7f7f7f;
}
tabset [role=tab] span, .tab-group [role=tab] span {
display: block;
margin: 0 0 0.5rem 0;
}
tabset [role=tabpanel], .tab-group [role=tabpanel] {
background-color: var(--colour-white);
border: 1px solid var(--colour-grey);
background-color: #FFF;
border: 1px solid #7f7f7f;
border-top: none;
padding: 1rem;
z-index: 1;

View File

@ -0,0 +1,2 @@
a(href="#") Link with a tool tip
span(role="tooltip" inert tip-position="right") Tool tip content

View File

@ -0,0 +1,2 @@
a(href="#") Link with a tool tip
span(role="tooltip" inert tip-position="right") Tool tip content

View File

@ -1,6 +1,7 @@
//- DS2 core (c) 2024 Alexander McIlwraith
//- Licensed under CC BY-SA 4.0
$font-body: sans-serif !default;
$tooltip-border-radius: .5rem !default;
$tooltip-dark-allow: true !default;
$tooltip-dark-background: #1f2127 !default;
@ -29,6 +30,7 @@ $tooltip-pointer-top: conic-gradient(from 150deg at top, rgba(0, 0, 0, 0), #000
border-radius: $tooltip-border-radius;
color: $tooltip-light-foreground;
filter: $tooltip-light-drop-shadow;
$font-family: $font-body;
font-size: 1rem;
font-weight: 400;
inline-size: max-content;

View File

@ -0,0 +1,51 @@
//- DS2 core (c) 2024 Alexander McIlwraith
//- Core licensed under CC BY-SA 4.0
extends ../../../core/_master-pattern
block content
+h(0)
p Tooltips provide brief information messaging through a mouse or keyboard hover.
+h(1)
p Use tool tips to provide additional information. Don't use tooltips for that is required to complete an interaction as the information disappears when it loses the hover state.
p Use tooltips to help differentiate between multiple, close, similar options.
+h(2)
p.notification-box.info Currently, there is no easy way to activate a hover without with pure CSS without using a keyboard or mouse. Level4 media queries aim to solve that.
p Either form works.
sticky-note.blue "Either form works": What are the two forms.
| Place the #[code.language-html.inline tooltip] inside another element for the tooltip to be 'linked to that element.' A container element may need to be added for a single tag element, such as a input field.
p Tool tip positions are:
ul
li top / block-start
li right / inline-end
li bottom / block-end
li left / inline-start
p
include _tooltip.pug
tabset#tooltip
pre.language-html(tab="html")
include _tooltip.pug
pre.language-pug(tab="pug")
include _tooltip.pp
pre.language-css(tab="css")
include tooltip.css
div(tab="scss")
+h(3)
pre.language-sass.
@import "scss/core/tooltip/_tooltip";
@include tooltip;
+h(4)
pre.language-sass
include _tooltip.scss

View File

@ -74,7 +74,7 @@
"lighter lighter lighter darker darker darker"
"notes notes notes notes notes notes";
grid-template-columns: repeat(6, 1fr);
grid-template-rows: repeat(2, 1.5rem) 10rem repeat(3, max-content); // 3rem repeat(2, 2rem) 1.5rem repeat(3, max-content);
grid-template-rows: repeat(2, 1.5rem) repeat(4, max-content); // 3rem repeat(2, 2rem) 1.5rem repeat(3, max-content);
padding: 1rem;
width: 20rem;
max-width: 318px;
@ -114,7 +114,7 @@
display: grid;
gap: .5rem;
grid-template-columns: repeat(3, 1fr);
grid-template-rows: 2.5rem repeat(2, max-content);
grid-template-rows: repeat(3, max-content);
.result {
align-items: center;
border-radius: .5rem;
@ -187,7 +187,7 @@
padding: .5rem;
width: 20rem;
max-width: 318px;
height: 10.5rem;
height: max-contents;
display: grid;
gap: .5rem;
@ -230,6 +230,7 @@
display: block;
width: 100%;
place-self: stretch;
text-align: center;
span {
border: none;
font-size: .9rem;

View File

@ -12,21 +12,18 @@ $tooltip-dark-allow: false;
@use 'sass:math';
// We recommend explicitly using the underscore when referring to pattern scss
// as you may have also created a version that compiles to css to display in
// your pattern.
@import "core";
@import "../pg/patterns/components/sticky-note-core/_sticky-note";
@import "../pg/patterns/components/tooltip-core/_tooltip";
@import "../pg/patterns/components/switch-core/_switch";
@import "../pg/patterns/layouts/breakpoints-core/_breakpoints";
@import "../pg/patterns/layouts/header-core/_header";
@import "../pg/patterns/layouts/tabs-core/_tabs";
@import "../pg/patterns/status-core/_status";
@import "../pg/patterns/core/sticky-note/_sticky-note";
@import "../pg/patterns/core/switch/_switch";
@import "../pg/patterns/core/tooltip/_tooltip";
@import "../pg/patterns/core/breakpoints/_breakpoints";
@import "../pg/patterns/core/header/_header";
@import "../pg/patterns/core/tabs/_tabs";
@import "../pg/patterns/core/status/_status";
* {
box-sizing: border-box;
@ -38,6 +35,9 @@ html {
@include break(-md) {
font-size: calc($font-size + 2pt);
}
&.show-breakpoints {
@include breakpoint-debug;
}
}
@include core-colour-samples;
@ -46,6 +46,10 @@ html {
@include sticky-note;
@include status;
article[data-status=deprecated]:not(.show-deprecated) {
display: none;
}
body {
margin: 0;
padding: 0;
@ -86,18 +90,24 @@ body {
}
p.deprecated-switch {
p.info-switches {
align-items: center;
display: grid;
gap: .25rem;
grid-column: 2 / 4;
grid-row: 3;
grid-template-columns: auto repeat(2, max-content);
text-align: right;
@include switch;
label {
text-align: left;;
}
}
main {
display: block;
grid-column: 1 / -1;
grid-row: 4;
padding: 0 1rem;
@include break(-md) {
grid-row: 3;