diff --git a/docs/components/balloon.ejs b/docs/components/balloon.ejs index 9180f0b..18ecf8f 100644 --- a/docs/components/balloon.ejs +++ b/docs/components/balloon.ejs @@ -20,6 +20,25 @@ You will need to set up an event for the control to trigger the balloon.

- <%- example(``) %> + <%- example(` + + + `) %> + +

+ To change the position of the balloon, which subsequently change the placement of its tail, combine + the respective vertical and horizontal classes: +

+ + <%- example(` +
This balloon is positioned bottom right of the source control (default behavior).
+ + + + `) %> +

\ No newline at end of file diff --git a/docs/components/searchbox.ejs b/docs/components/searchbox.ejs new file mode 100644 index 0000000..daccae5 --- /dev/null +++ b/docs/components/searchbox.ejs @@ -0,0 +1,34 @@ +
+ +
+
+ With a Search box, users can quickly locate specific objects or text within a large set of data by + filtering or highlighting matches. + + +
+ +

+ There are 2 variants of the search box available. +

+ +

+ An instant search, where the results are displayed immediately as the user types, can be rendered + just by specifying a type="search" attribute on an input element: +

+ + <%- example(``) %> + +

+ A regular search, where a search is performed when the user clicks the search button, requires + a search input and a button wrapped inside a container a container element with the class searchbox. +

+ + <%- example(` + `) %> +
+
\ No newline at end of file diff --git a/docs/docs.css b/docs/docs.css index 044e36a..e7faae2 100644 --- a/docs/docs.css +++ b/docs/docs.css @@ -142,6 +142,10 @@ blockquote footer { width: 450px; } +[role="tooltip"]:not([id]) { + margin: 2em 0; +} + @media (max-width: 480px) { aside { display: none; diff --git a/docs/index.html.ejs b/docs/index.html.ejs index 443d856..4a532f0 100644 --- a/docs/index.html.ejs +++ b/docs/index.html.ejs @@ -79,6 +79,7 @@ <%- include('components/optionbutton') -%> <%- include('components/progressbar') -%> <%- include('components/scrollbar') -%> + <%- include('components/searchbox') -%> <%- include('components/slider') -%> <%- include('components/spinner') -%> <%- include('components/tabs') -%> diff --git a/docs/script.js b/docs/script.js index 53fae37..a7c5ea7 100644 --- a/docs/script.js +++ b/docs/script.js @@ -40,6 +40,7 @@ document if (e.key === "Enter") { tooltip.removeAttribute("hidden"); tooltip.style.top = input.offsetTop + input.offsetHeight + 15 + "px"; + tooltip.style.zIndex = 1; } if (e.key === "Backspace") { tooltip.setAttribute("hidden", true); diff --git a/docs/sections/navigation.ejs b/docs/sections/navigation.ejs index a1c1906..2d248a3 100644 --- a/docs/sections/navigation.ejs +++ b/docs/sections/navigation.ejs @@ -31,6 +31,7 @@
  • OptionButton
  • ProgressBar
  • Scrollbar
  • +
  • SearchBox
  • Slider
  • Spinner
  • Tabs
  • diff --git a/gui/_balloon.scss b/gui/_balloon.scss index 85a15b7..316a91d 100644 --- a/gui/_balloon.scss +++ b/gui/_balloon.scss @@ -1,6 +1,9 @@ :root { --balloon-border-color: rgba(0, 0, 0, 0.4); + --balloon-tail-top: url("data:image/svg+xml,%3Csvg width='20' height='20' viewBox='0 0 20 20' fill='none' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M0.5 1.5V19.5H18.5L0.5 1.5Z' fill='%23fff' stroke='%23fff'/%3E%3Cpath d='M1 19.5H0.5V1.5L18.5 19.5H18' stroke='%23939393'/%3E%3C/svg%3E"); + --balloon-tail-bottom: url("data:image/svg+xml,%3Csvg width='20' height='20' viewBox='0 0 20 20' fill='none' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M0.5 1.5V19.5H18.5L0.5 1.5Z' fill='%23ddd' stroke='%23ddd'/%3E%3Cpath d='M1 19.5H0.5V1.5L18.5 19.5H18' stroke='%23939393'/%3E%3C/svg%3E"); --balloon-tail-size: 18px; + --balloon-tail-offset: 1em; } [role="tooltip"] { @@ -14,14 +17,42 @@ &::before { content: ""; position: absolute; - background: url("./icon/balloon-tail.svg"); + background: var(--balloon-tail-top); width: var(--balloon-tail-size); height: var(--balloon-tail-size); top: -var(--balloon-tail-size); - left: 1em; + left: var(--balloon-tail-offset); } &[id] { position: absolute; } + + &.is-top { + &::before { + background: var(--balloon-tail-bottom); + bottom: -var(--balloon-tail-size); + top: unset; + transform: scale(-1); + } + + &.is-right { + &::before { + transform: scaleY(-1); + } + } + } + + &.is-left { + &::before { + left: unset; + right: var(--balloon-tail-offset); + } + + &.is-bottom { + &::before { + transform: scaleX(-1); + } + } + } } diff --git a/gui/_button.scss b/gui/_button.scss index cc1d779..cc7c5f6 100644 --- a/gui/_button.scss +++ b/gui/_button.scss @@ -11,12 +11,7 @@ button, min-height: 23px; padding: 0 12px; text-align: center; - background: linear-gradient( - to bottom, - var(--button-face) 45%, - var(--button-shade-light) 45%, - var(--button-shade-dark) - ); + background: var(--button-gradient); &:disabled { background: var(--button-face-disabled); @@ -27,22 +22,14 @@ button, &:not(:disabled) { &:hover { border-color: var(--button-border-color-hovered); - background: linear-gradient( - to bottom, - var(--button-face-hover) 45%, - var(--button-shade-light-hovered) 45% - ); + background: var(--button-gradient-hovered); } &:active, &.active { box-shadow: none; border-color: var(--button-border-color-active); - background: linear-gradient( - to bottom, - var(--button-face-active) 45%, - var(--button-shade-light-active) 45% - ); + background: var(--button-gradient-active); } } diff --git a/gui/_dropdown.scss b/gui/_dropdown.scss index 2651c3a..da50913 100644 --- a/gui/_dropdown.scss +++ b/gui/_dropdown.scss @@ -12,24 +12,14 @@ select:not([multiple]) { appearance: none; position: relative; padding-right: 30px; - background: url("./icon/button-down.svg"), - linear-gradient( - to bottom, - var(--button-face) 45%, - var(--button-shade-light) 45%, - var(--button-shade-dark) - ); + background: url("./icon/button-down.svg"), var(--button-gradient); background-position: center right; background-repeat: no-repeat; &:hover { border-color: var(--button-border-color-hovered); background-image: url("./icon/button-down.svg"), - linear-gradient( - to bottom, - var(--button-face-hover) 45%, - var(--button-shade-light-hovered) 45% - ); + var(--button-gradient-hovered); } &:focus { @@ -37,10 +27,6 @@ select:not([multiple]) { border-color: var(--button-border-color-active); box-shadow: unset; background-image: url("./icon/button-down.svg"), - linear-gradient( - to bottom, - var(--button-face-active) 45%, - var(--button-shade-light-active) 45% - ); + var(--button-gradient-active); } } diff --git a/gui/_searchbox.scss b/gui/_searchbox.scss new file mode 100644 index 0000000..6201b35 --- /dev/null +++ b/gui/_searchbox.scss @@ -0,0 +1,63 @@ +:root { + --search-icon: url("./icon/search.svg"); + --search-button: var(--search-icon) no-repeat center; +} + +[type="search"] { + height: 24px; + font: var(--font); + padding: 3px 6px; + border: 1px solid transparent; + border-radius: 2px; + background-color: var(--button-highlight); + box-shadow: inset 1px 1px 0 var(--button-border-color), inset -1px -1px 0 #ccc; + box-sizing: border-box; + min-width: 187px; + + &:placeholder-shown { + background-size: 14px; + background-position: calc(100% - 8px) center; + background-image: var(--search-icon); + background-repeat: no-repeat; + } + + &:focus { + outline: none; + } + + &::placeholder { + font-style: italic; + } + + .searchbox & { + padding-right: 26px; + + & + [aria-label="search"] { + position: absolute; + top: 1px; + right: 1px; + border-radius: 0; + padding: 0; + min-width: 26px; + min-height: 22px; + background: var(--search-button), var(--button-gradient); + background-size: 14px; + + &:hover { + background: var(--search-button), var(--button-gradient-hovered); + background-size: 14px; + } + + &:active { + background: var(--search-button), var(--button-gradient-active); + background-size: 14px; + box-shadow: inset 1px 1px 2px #37698f; + } + } + } +} + +.searchbox { + position: relative; + display: inline-block; +} diff --git a/gui/_variables.scss b/gui/_variables.scss index 14d4352..ff443c5 100644 --- a/gui/_variables.scss +++ b/gui/_variables.scss @@ -12,7 +12,8 @@ --button-shade-light-hovered: #b3e0f9; --button-shade-light-active: #86c6e8; --button-shade-dark: #bbb; - --button-shadow: inset 0 -1px 1px rgba(255, 255, 255, 0.8), inset 0 1px 1px #fff; + --button-shadow: inset 0 -1px 1px rgba(255, 255, 255, 0.8), + inset 0 1px 1px #fff; --button-border: 1px solid; --button-border-color: #8e8f8f; --button-border-color-default: #5586a3; @@ -20,6 +21,22 @@ --button-border-color-active: #6d91ab; --button-border-color-disabled: #aeb2b5; --button-text-color-disabled: #838383; + --button-gradient: linear-gradient( + to bottom, + var(--button-face) 45%, + var(--button-shade-light) 45%, + var(--button-shade-dark) + ); + --button-gradient-hovered: linear-gradient( + to bottom, + var(--button-face-hover) 45%, + var(--button-shade-light-hovered) 45% + ); + --button-gradient-active: linear-gradient( + to bottom, + var(--button-face-active) 45%, + var(--button-shade-light-active) 45% + ); --element-spacing: 8px; --grouped-element-spacing: 6px; diff --git a/gui/icon/balloon-tail.svg b/gui/icon/balloon-tail.svg deleted file mode 100644 index a9ade97..0000000 --- a/gui/icon/balloon-tail.svg +++ /dev/null @@ -1,4 +0,0 @@ - - - - diff --git a/gui/icon/search.svg b/gui/icon/search.svg new file mode 100644 index 0000000..ff1e649 --- /dev/null +++ b/gui/icon/search.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/gui/index.scss b/gui/index.scss index 324a092..d0ef29c 100644 --- a/gui/index.scss +++ b/gui/index.scss @@ -17,6 +17,7 @@ @import "_menu.scss"; @import "_progressbar.scss"; @import "_radiobutton.scss"; +@import "_searchbox.scss"; @import "_slider.scss"; @import "_spinner.scss"; @import "_tabs.scss";