head 0.0.1 → 0.0.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 11835ad46d870dcdc415a869c67328331f67eff34b8d1e704c2df9b184f48e30
4
- data.tar.gz: f913154fbd0cb1b807fec777b50a736b25352232d88d67ea60d2ecc9abc489e2
3
+ metadata.gz: 64555f34c0083982a934eab9077ed59c080d25e5c30d649c45bb72f91d5a4d7d
4
+ data.tar.gz: 7d56527224c27361e457345eabeea6fedacda3d820608f50bd0e2afd2463f59a
5
5
  SHA512:
6
- metadata.gz: a79743be804f0101a40d6696fd4266641ac1741bd7451d2e5558ff6b6b90160c6461bb40124b4c8938a903e0101193ff383c7099a7df01c3ba8fa56df961fc92
7
- data.tar.gz: 4ec8047baec015c2a05d96914ce983f81e2c4e3c4316980b86d4226a00948d8816039512f4a9a6a8a3a61a5360dbf0f6f266d8b6b734933a29fce3eee7df22cb
6
+ metadata.gz: d755be54df9724b2c9dea550f04bb10d3c211ea6d06028eb6dedee133f603ab80a614515f2e038a651ff6cd5c83c18598bbb14098b7f0032f7e5d52c61606629
7
+ data.tar.gz: 23c1c19da4691d95d45411ae3c13c15ddc847d0dfa9767d415569c2e994119015dcbe9e3daf47979d4340c1f9feaf33fdd57a377df5b5ad7238cc9a72f3402e3
Binary file
@@ -7,13 +7,21 @@
7
7
  "iconSets": [
8
8
  {
9
9
  "selection": [
10
+ {
11
+ "order": 10,
12
+ "id": 8,
13
+ "name": "volume",
14
+ "prevSize": 32,
15
+ "code": 59655,
16
+ "tempChar": ""
17
+ },
10
18
  {
11
19
  "order": 9,
12
20
  "id": 7,
13
21
  "name": "gear",
14
22
  "prevSize": 32,
15
23
  "code": 59654,
16
- "tempChar": ""
24
+ "tempChar": ""
17
25
  },
18
26
  {
19
27
  "order": 8,
@@ -21,7 +29,7 @@
21
29
  "name": "question-mark",
22
30
  "prevSize": 32,
23
31
  "code": 59648,
24
- "tempChar": ""
32
+ "tempChar": ""
25
33
  },
26
34
  {
27
35
  "order": 7,
@@ -29,7 +37,7 @@
29
37
  "name": "bell-ringing",
30
38
  "prevSize": 32,
31
39
  "code": 59649,
32
- "tempChar": ""
40
+ "tempChar": ""
33
41
  },
34
42
  {
35
43
  "order": 6,
@@ -37,7 +45,7 @@
37
45
  "name": "bell",
38
46
  "prevSize": 32,
39
47
  "code": 59650,
40
- "tempChar": ""
48
+ "tempChar": ""
41
49
  },
42
50
  {
43
51
  "order": 5,
@@ -45,7 +53,7 @@
45
53
  "name": "magnifier",
46
54
  "prevSize": 32,
47
55
  "code": 59651,
48
- "tempChar": ""
56
+ "tempChar": ""
49
57
  },
50
58
  {
51
59
  "order": 4,
@@ -53,7 +61,7 @@
53
61
  "name": "bars-thin",
54
62
  "prevSize": 32,
55
63
  "code": 59652,
56
- "tempChar": ""
64
+ "tempChar": ""
57
65
  },
58
66
  {
59
67
  "order": 3,
@@ -61,7 +69,7 @@
61
69
  "name": "bars-bold",
62
70
  "prevSize": 32,
63
71
  "code": 59653,
64
- "tempChar": ""
72
+ "tempChar": ""
65
73
  }
66
74
  ],
67
75
  "id": 0,
@@ -75,6 +83,21 @@
75
83
  "height": 1024,
76
84
  "prevSize": 32,
77
85
  "icons": [
86
+ {
87
+ "id": 8,
88
+ "paths": [
89
+ "M480.896 190.848v-105.515h62.251v105.515c-10.368-0.768-20.736-1.195-31.147-1.195s-20.779 0.427-31.104 1.195zM327.808 233.6l-40.448-97.579c18.603-9.045 37.803-16.981 57.557-23.808l40.363 97.579c-8.96 2.901-17.835 6.187-26.624 9.728-10.539 4.267-20.821 8.96-30.848 14.080zM641.237 210.645l41.045-97.28c19.712 6.912 38.827 15.019 57.387 24.192l-41.045 97.237c-10.837-5.547-21.931-10.667-33.237-15.275-7.979-3.243-16-6.187-24.149-8.875zM875.691 413.056l97.579-40.405c9.045 18.603 16.981 37.76 23.851 57.515l-97.621 40.405c-2.901-8.96-6.187-17.835-9.728-26.667-4.267-10.539-8.96-20.779-14.080-30.848zM777.429 287.872l74.624-74.581c15.531 13.781 30.208 28.459 43.989 43.989l-74.624 74.624c-6.741-7.851-13.781-15.445-21.163-22.827s-15.019-14.464-22.827-21.205zM202.581 331.861l-74.624-74.581c13.739-15.531 28.459-30.251 43.989-43.989l74.624 74.581c-7.808 6.741-15.445 13.781-22.827 21.163s-14.421 15.019-21.163 22.827zM148.309 781.44l-97.579 40.363c-9.045-18.56-16.981-37.76-23.851-57.515l97.621-40.405c2.901 8.96 6.187 17.835 9.728 26.667 4.267 10.539 8.96 20.821 14.080 30.891zM898.645 726.443l97.28 41.045c-6.912 19.669-15.019 38.827-24.192 57.344l-97.237-41.003c5.547-10.837 10.667-21.931 15.275-33.28 3.243-7.936 6.187-16 8.875-24.107zM1024 628.352h-105.557c0.811-10.325 1.152-20.693 1.152-31.147 0-10.411-0.384-20.779-1.152-31.104h105.557v62.251zM821.419 862.592l74.624 74.624c-13.781 15.531-28.459 30.251-44.032 44.032l-74.581-74.624c7.851-6.741 15.445-13.824 22.827-21.205s14.421-15.019 21.163-22.827zM125.355 468.011l-97.28-41.045c6.912-19.669 15.019-38.827 24.192-57.344l97.237 41.003c-5.547 10.837-10.667 21.931-15.275 33.28-3.243 7.936-6.187 16-8.875 24.107zM105.557 628.352h-105.557v-62.251h105.557c-0.811 10.325-1.152 20.693-1.152 31.104-0.043 10.453 0.341 20.821 1.152 31.147zM246.571 906.624l-74.752 74.709-43.989-43.989 74.752-74.752c6.741 7.851 13.781 15.445 21.163 22.827s15.019 14.421 22.827 21.205zM512 274.901c-177.707 0-322.304 144.597-322.304 322.304s144.597 322.304 322.304 322.304 322.304-144.597 322.304-322.304-144.597-322.304-322.304-322.304zM414.933 567.765l-92.075-92.075 60.288-60.373 92.075 92.075-60.288 60.373z"
90
+ ],
91
+ "attrs": [
92
+ {}
93
+ ],
94
+ "isMulticolor": false,
95
+ "isMulticolor2": false,
96
+ "grid": 0,
97
+ "tags": [
98
+ "volume"
99
+ ]
100
+ },
78
101
  {
79
102
  "id": 7,
80
103
  "paths": [
@@ -138,7 +161,7 @@
138
161
  {
139
162
  "id": 3,
140
163
  "paths": [
141
- "M1015.851 923.563l-264.747-264.747c49.792-68.48 79.232-152.704 79.232-243.669 0-228.907-186.24-415.147-415.189-415.147-228.907 0-415.147 186.24-415.147 415.147 0 228.949 186.24 415.147 415.147 415.147 86.784 0 167.381-26.752 234.112-72.448l266.155 266.155 100.437-100.437zM121.771 415.147c0-161.792 131.627-293.419 293.419-293.419s293.419 131.627 293.419 293.419-131.627 293.419-293.419 293.419c-161.835 0-293.419-131.627-293.419-293.419z"
164
+ "M903.339 1024l-315.179-315.179c-59.221 37.291-129.024 59.179-204.16 59.179-212.096 0-384-171.904-384-384s171.904-384 384-384 384 171.904 384 384c0 75.136-21.931 144.981-59.179 204.16l315.179 315.179-120.661 120.661zM384 682.667c164.651 0 298.667-133.973 298.667-298.667s-134.016-298.667-298.667-298.667-298.667 133.973-298.667 298.667 134.016 298.667 298.667 298.667z"
142
165
  ],
143
166
  "attrs": [
144
167
  {}
@@ -1,2 +1,3 @@
1
1
  import "head/knob"
2
2
  import "head/wing"
3
+ import "head/sidebar"
@@ -14,7 +14,7 @@ document.addEventListener('DOMContentLoaded', function () {
14
14
 
15
15
  // Check screen size
16
16
  const mainMenuWing = document.querySelector(`.js-head-wing[data-identifier="mainmenu"]`)
17
- const tight = getComputedStyle(mainMenuWing).getPropertyValue('position') == 'absolute'
17
+ const tight = mainMenuWing ? getComputedStyle(mainMenuWing).getPropertyValue('position') === 'absolute' : false
18
18
 
19
19
  // Handle current wing
20
20
  const wing = document.querySelector(`.js-head-wing[data-identifier="${identifier}"]`)
@@ -0,0 +1,39 @@
1
+ document.addEventListener('DOMContentLoaded', function() {
2
+ document.querySelectorAll('.js-head-sidebar__category').forEach(function (category) {
3
+ console.debug("Binding to Sidebar Category")
4
+ const href = category.getAttribute('href')
5
+
6
+ // If this category doesn't open a secondary sidebar, it is a standalone link.
7
+ if (href != '#') return
8
+
9
+ category.addEventListener('click', function(event) {
10
+ event.preventDefault()
11
+ const category = event.currentTarget
12
+
13
+ // The identifier of a category always matches that of its links list.
14
+ const identifier = category.dataset.identifier
15
+ const active = category.classList.contains('is-active')
16
+ const links = document.querySelector(`.js-head-sidebar__links[data-identifier="${identifier}"]`)
17
+
18
+ // Close all others
19
+ document.querySelectorAll('.js-head-sidebar__links').forEach((someLinks) => {
20
+ if (links == someLinks) return
21
+
22
+ someLinks.classList.remove('is-active')
23
+ const categoryClass = `.js-head-sidebar__category[data-identifier="${someLinks.dataset.identifier}"]`
24
+ document.querySelectorAll(categoryClass).forEach((someCategory) => {
25
+ someCategory.classList.remove('is-active')
26
+ })
27
+ })
28
+
29
+ // Now toggle the desired one.
30
+ if (active) {
31
+ category.classList.remove('is-active')
32
+ links.classList.remove('is-active')
33
+ } else {
34
+ category.classList.add('is-active')
35
+ links.classList.add('is-active')
36
+ }
37
+ })
38
+ })
39
+ })
@@ -1,3 +1,4 @@
1
+ @use "iglu/responsive"
1
2
  @use "iglu/font-size"
2
3
  @use "iglu/spacing"
3
4
  @use "head/settings/colors"
@@ -20,9 +21,11 @@
20
21
  &:active
21
22
  color: colors.$white
22
23
 
24
+ &--mainmenu
25
+ display: grid
26
+
23
27
  &--identicon
24
28
  max-width: 1em
25
- border-radius: 50%
26
29
  aspect-ratio: 1
27
30
  display: grid
28
31
  place-items: center
@@ -34,12 +37,14 @@
34
37
  object-fit: contain
35
38
 
36
39
  &--avatar
37
- max-width: 1em
38
- border-radius: 50%
40
+ max-width: 1.4em
39
41
  aspect-ratio: 1
40
42
  display: grid
41
43
  place-items: center
42
44
  overflow: hidden
45
+ padding: 0
46
+ // padding-right: 0.25em
47
+ padding-left: 0.25em
43
48
 
44
49
  img
45
50
  width: 100%
@@ -47,3 +52,12 @@
47
52
  object-fit: contain
48
53
  clip-path: circle()
49
54
  background-color: #fff
55
+
56
+
57
+ // Keep this breakpoint analogous to wing.sass
58
+ +responsive.xlarge
59
+ .c-head-knob
60
+
61
+ &--mainmenu
62
+ display: none
63
+
@@ -0,0 +1,99 @@
1
+ @use "iglu/spacing"
2
+ @use "iglu/font-size"
3
+ @use "head/settings/colors"
4
+ @use "head/tools/link"
5
+
6
+ .c-head-sidebar
7
+ display: grid
8
+ grid-template-columns: auto 1fr
9
+ height: 100%
10
+ align-items: start
11
+ +font-size.default
12
+
13
+ &__categories
14
+ display: grid
15
+
16
+ &--right
17
+ .c-head-sidebar__categories
18
+ order: 2
19
+
20
+ &__secondary
21
+ overflow: hidden
22
+ background-color: rgba(255, 255, 255, 0.14) // Corrsponds to 10% change in underlying color
23
+ height: 100%
24
+
25
+ &__category
26
+ display: grid
27
+ justify-content: center
28
+ grid-template-areas: "icon" "name"
29
+ padding-top: 0.2em
30
+ padding-bottom: 0.2em
31
+ position: relative
32
+ text-decoration: none
33
+ +spacing.padding-horizontal--tiny
34
+
35
+ @each $column in category-icon category-name
36
+ &__#{$column}
37
+ grid-area: #{$column}
38
+
39
+ +link.states
40
+ color: colors.$moon-gray
41
+
42
+ &:hover
43
+ color: colors.$white
44
+
45
+ &.is-active
46
+ color: colors.$white
47
+ background-color: rgba(255, 255, 255, 0.14) // Corrsponds to 10% change in underlying color
48
+
49
+ &-icon
50
+ text-align: center
51
+ +font-size.huge
52
+
53
+ &-name
54
+ +font-size.smaller
55
+
56
+ &__links
57
+ display: none
58
+
59
+ &.is-active
60
+ display: block
61
+
62
+ &__link
63
+ grid-column-gap: 0.6rem
64
+ display: grid
65
+ align-items: center
66
+ grid-template-columns: auto 1fr
67
+ grid-template-areas: "icon name"
68
+ padding-right: 0.5rem
69
+ padding-left: 0.5rem
70
+ text-decoration: none
71
+ height: 100%
72
+ +spacing.padding-vertical--tiny
73
+
74
+ @each $column in link-icon link-name
75
+ &__#{$column}
76
+ grid-area: #{$column}
77
+
78
+ +link.states
79
+ color: colors.$moon-gray
80
+
81
+ &:hover
82
+ color: colors.$white
83
+
84
+ &:active
85
+ color: colors.$white
86
+
87
+ &.is-active
88
+ color: colors.$white
89
+ background-color: rgba(255, 255, 255, 0.14)
90
+
91
+ &-name
92
+ white-space: nowrap
93
+ +font-size.small
94
+
95
+ &-icon
96
+ +font-size.larger
97
+
98
+ &-separator
99
+ +spacing.margin-top--smaller
@@ -1,5 +1,6 @@
1
1
  @use "iglu/spacing"
2
2
  @use "head/settings/colors"
3
+ @use "iglu/font-size"
3
4
 
4
5
  .c-head-theater
5
6
  height: 100%
@@ -7,10 +8,12 @@
7
8
  grid-template-rows: auto 1fr
8
9
 
9
10
  &__roof
10
- background-color: #444
11
+ background-color: colors.$granite-gray
11
12
  display: grid
13
+ line-height: 1 // Conformity of knobs
12
14
  align-items: center
13
- grid-template-columns: auto 1fr auto
15
+ // Keep Logo centered even if left and right menus differ in width
16
+ grid-template-columns: 1fr 1fr 1fr
14
17
  grid-template-areas: "knobs--left logo knobs--right"
15
18
 
16
19
  @each $column in knobs--left logo knobs--right
@@ -35,6 +38,7 @@
35
38
  color: colors.$white
36
39
  padding: 0.3rem
37
40
  overflow: auto // Clip wide logos on small screens
41
+ +font-size.gigantic
38
42
 
39
43
  &:active
40
44
  top: 1px
@@ -4,8 +4,9 @@
4
4
  .c-head-wing
5
5
  display: none
6
6
  // 320px is the min screen width we support.
7
- // Our sidebar cannot be bigger, and it needs to leave some space
8
- // at the right so that a click/tap there can close the sidebar.
7
+ // On devices that are that narrow, the sidebar needs to fit in,
8
+ // as well as a blank area on the right to close the sidebar with a tap.
9
+ // So the sidebar is limited to less than 320px on narrow devices.
9
10
  max-width: 265px
10
11
  height: 100%
11
12
  z-index: 1000
@@ -13,22 +14,12 @@
13
14
  background: colors.$granite-gray
14
15
  color: colors.$white
15
16
 
16
- &--left
17
- // On rather large screens, always show the main menu in left sidebar
18
- +responsive.xlarge-container
19
- position: static
20
-
21
- &[data-identifier="mainmenu"]
22
- // We "force" this item to be active without having the `is-active` class.
23
- display: block
24
- // So we need some way to deactivate it again using JS.
25
- &.is-force-deactive
26
- display: none
27
-
28
17
  &--right
29
18
  right: 0
19
+ position: inherit
30
20
 
31
- // On very very large screens, show notifications sidebar on the right.
21
+ // On very very large screens, permanently show notifications sidebar on the right.
22
+ // Using container queries for this, because the main menu on the left may affect the layout.
32
23
  +responsive.xxlarge-container
33
24
  position: static
34
25
 
@@ -57,14 +48,19 @@
57
48
  +responsive.xlarge-container
58
49
  display: none
59
50
 
51
+ // Keep this breakpoint analogous to knob.sass
52
+ +responsive.xlarge
53
+ .c-head-wing
60
54
 
61
- // +responsive.xxlarge
62
- // .c-head-wing
63
-
64
- // // We "force" this item to be active without having the `is-active` class.
65
- // &[data-identifier="mainmenu"]
66
- // display: block
55
+ &--left
56
+ // On rather large screens, always show the main menu in left sidebar
57
+ position: static
58
+ // On wide screens, it's ok to have a wider sidebar to fit all text.
59
+ max-width: 350px
67
60
 
68
- // // So we need some way to deactivate it again using JS.
69
- // &.is-force-deactive
70
- // display: none
61
+ &[data-identifier="mainmenu"]
62
+ // We "force" this item to be active without having the `is-active` class.
63
+ display: block
64
+ // // So we need some way to deactivate it again using JS.
65
+ // &.is-force-deactive
66
+ // display: none
@@ -2,5 +2,5 @@
2
2
  font-family: 'headicons'
3
3
  font-weight: normal
4
4
  font-style: normal
5
- src: url('head/headicons.woff') format('woff')
5
+ src: url('/head/headicons.woff') format('woff')
6
6
 
@@ -3,6 +3,7 @@
3
3
  @use "./generics/flip"
4
4
  @use "./generics/fonts"
5
5
 
6
+ @use "./components/sidebar"
6
7
  @use "./components/theater"
7
8
  @use "./components/knob"
8
9
  @use "./components/wing"
@@ -1,4 +1,4 @@
1
- @use 'head/settings/icons'
1
+ @use 'head/settings/headicons'
2
2
 
3
3
  .o-headicon
4
4
  font-family: "headicons"
@@ -13,16 +13,28 @@
13
13
 
14
14
  .o-headicon--bars-bold
15
15
  &:before
16
- content: icons.$bars-bold
16
+ content: headicons.$bars-bold
17
+
18
+ .o-headicon--bars-thin
19
+ &:before
20
+ content: headicons.$bars-bold
17
21
 
18
22
  .o-headicon--magnifier
19
23
  &:before
20
- content: icons.$magnifier
24
+ content: headicons.$magnifier
21
25
 
22
26
  .o-headicon--bell
23
27
  &:before
24
- content: icons.$bell
28
+ content: headicons.$bell
29
+
30
+ .o-headicon--bell-ringing
31
+ &:before
32
+ content: headicons.$bell-ringing
25
33
 
26
34
  .o-headicon--gear
27
35
  &:before
28
- content: icons.$gear
36
+ content: headicons.$gear
37
+
38
+ .o-headicon--question-mark
39
+ &:before
40
+ content: headicons.$question-mark
@@ -10,5 +10,6 @@ $jade-green: rgb(0, 190, 130)
10
10
  $granite-gray: rgb(70, 70, 70)
11
11
  $steel-gray: color.adjust($granite-gray, $lightness: 25%)
12
12
  $silver-gray: color.adjust($granite-gray, $lightness: 50%)
13
+ $moon-gray: color.adjust($granite-gray, $lightness: 65%)
13
14
 
14
15
  $transparent-gray: rgba(100, 100, 100, 0.5)
@@ -1,3 +1,4 @@
1
+ $volume: "\e907";
1
2
  $gear: "\e906";
2
3
  $question-mark: "\e900";
3
4
  $bell-ringing: "\e901";
@@ -1,11 +1,11 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Head
4
- class Knob < ApplicationComponent
4
+ class Knob < ::Head::ApplicationComponent
5
5
  erb_template <<~ERB
6
6
  <%= link_to(url, class: classes, data: { identifier: id, group: group }, **options.except(:url)) do %>
7
7
  <% if icon %>
8
- <i class="o-headicon <%= icon_class%><%= %>"></i>
8
+ <i class="o-headicon <%= icon_class%>"></i>
9
9
  <% end %>
10
10
 
11
11
  <%= content %>
@@ -25,9 +25,10 @@ module Head
25
25
 
26
26
  def icon
27
27
  return manual_icon if manual_icon
28
- return :'bars-bold' if preset_mainmenu?
28
+ return :'bars-thin' if preset_mainmenu?
29
29
  return :bell if preset_notifications?
30
30
  return :gear if preset_settings?
31
+ return :'question-mark' if preset_help?
31
32
 
32
33
  :magnifier if preset_search?
33
34
  end
@@ -44,6 +45,7 @@ module Head
44
45
  result = %w[c-head-knob js-head-knob]
45
46
  result.push 'c-head-knob--identicon' if preset_identicon?
46
47
  result.push 'c-head-knob--avatar' if preset_avatar?
48
+ result.push 'c-head-knob--mainmenu' if preset_mainmenu?
47
49
  result
48
50
  end
49
51
 
@@ -67,6 +69,10 @@ module Head
67
69
  preset == :search
68
70
  end
69
71
 
72
+ def preset_help?
73
+ preset == :help
74
+ end
75
+
70
76
  def preset_identicon?
71
77
  preset == :identicon
72
78
  end
@@ -0,0 +1,34 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Head
4
+ class Sidebar < ::Head::ApplicationComponent
5
+ erb_template <<~ERB
6
+ <div data-group="<%= right ? :right : :left %>" class="c-head-sidebar <%= 'c-head-sidebar--right' if right %> ">
7
+ <% if categories.any? %>
8
+ <div class="c-head-sidebar__categories">
9
+ <% categories.each do |category| %>
10
+ <%= category %>
11
+ <% end %>
12
+ </div>
13
+
14
+ <div class="c-head-sidebar__secondary">
15
+ <% categories.select(&:submenu?).each do |category| %>
16
+ <div class="c-head-sidebar__links js-head-sidebar__links" data-identifier="<%= category.identifier %>">
17
+ <% category.links.each do |link| %>
18
+ <%= link %>
19
+ <% end %>
20
+ </div>
21
+ <% end %>
22
+ </div>
23
+ <% end %>
24
+ </div>
25
+ ERB
26
+
27
+ renders_many :categories, -> (**options) do
28
+ ::Head::Sidebars::Category.new(icon_class_prefix:, **options)
29
+ end
30
+
31
+ option :right, default: -> { false }
32
+ option :icon_class_prefix, default: -> {}
33
+ end
34
+ end
@@ -0,0 +1,51 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Head
4
+ module Sidebars
5
+ class Category < ::Head::ApplicationComponent
6
+ erb_template <<~ERB
7
+ <%= link_to(url, data:,
8
+ class: 'c-head-sidebar__category js-head-sidebar__category', **link) do %>
9
+ <%= content_tag :i, nil, class: icon_classes %>
10
+ <%= content_tag :div, name, class: 'c-head-sidebar__category-name' %>
11
+ <% end %>
12
+ ERB
13
+
14
+ renders_many :links, -> (**options) do
15
+ ::Head::Sidebars::Link.new(icon_class_prefix:, **options)
16
+ end
17
+
18
+ option :url, default: -> { '#' }
19
+ option :icon_class_prefix, default: -> {}
20
+ option :name
21
+ option :icon
22
+ option :link, default: -> { {} }
23
+
24
+ def css_classes
25
+ "c-head-sidebar__category #{'js-head-sidebar__category' if submenu?}"
26
+ end
27
+
28
+ def icon_classes
29
+ "#{icon_class_prefix}#{icon.to_s.gsub('_', '-')} c-head-sidebar__category-icon"
30
+ end
31
+
32
+ def data
33
+ return unless submenu?
34
+
35
+ { identifier: }
36
+ end
37
+
38
+ def submenu?
39
+ url == '#'
40
+ end
41
+
42
+ def with_separator
43
+ with_link(name: nil, icon: nil)
44
+ end
45
+
46
+ def identifier
47
+ @identifier ||= SecureRandom.hex
48
+ end
49
+ end
50
+ end
51
+ end
@@ -0,0 +1,11 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Head
4
+ module Sidebars
5
+ class Headline < ::Head::ApplicationComponent
6
+ erb_template <<~ERB
7
+ Headline
8
+ ERB
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,37 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Head
4
+ module Sidebars
5
+ class Link < ::Head::ApplicationComponent
6
+ erb_template <<~ERB
7
+ <%= link_to(url, class: link_classess, **link) do %>
8
+ <% if icon %>
9
+ <%= content_tag :i, nil, class: icon_classes %>
10
+ <% end %>
11
+ <%= content_tag :div, name, class: 'c-head-sidebar__link-name' %>
12
+ <% end %>
13
+ ERB
14
+
15
+ option :url, default: -> { '#' }
16
+ option :name
17
+ option :icon
18
+ option :link, default: -> { {} }
19
+ option :icon_class_prefix, default: -> {}
20
+ option :active, default: -> {}
21
+
22
+ def link_classess
23
+ "c-head-sidebar__link #{'c-head-sidebar__link-separator' unless icon} #{active?}".squish
24
+ end
25
+
26
+ def icon_classes
27
+ "#{icon_class_prefix}#{icon.to_s.gsub('_', '-')} c-head-sidebar__link-icon"
28
+ end
29
+
30
+ def active?
31
+ ::Head::Active.call(url: url_for(url),
32
+ condition: active,
33
+ current_path: request.original_fullpath)
34
+ end
35
+ end
36
+ end
37
+ end
@@ -1,7 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Head
4
- class Theater < ApplicationComponent
4
+ class Theater < ::Head::ApplicationComponent
5
5
  erb_template <<~ERB
6
6
  <div class="c-head-theater">
7
7
  <div class="c-head-theater__roof">
@@ -50,6 +50,11 @@ module Head
50
50
  with_wing(id: :mainmenu, &)
51
51
  end
52
52
 
53
+ def with_help(&)
54
+ with_knob(preset: :help, right: true)
55
+ with_wing(id: :help, right: true, &)
56
+ end
57
+
53
58
  def with_notifications(&)
54
59
  with_knob(preset: :notifications, right: true)
55
60
  with_wing(id: :notifications, right: true, &)
@@ -1,7 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Head
4
- class Wing < ApplicationComponent
4
+ class Wing < ::Head::ApplicationComponent
5
5
  erb_template <<~ERB
6
6
  <div class="<%= classes.join(' ') %>" data-identifier="<%= id %>" data-group="<%= group %>">
7
7
  <%= content %>
data/config/importmap.rb CHANGED
@@ -4,3 +4,4 @@ pin 'head', to: 'head/index.js'
4
4
 
5
5
  pin 'head/knob', to: 'head/knob.js'
6
6
  pin 'head/wing', to: 'head/wing.js'
7
+ pin 'head/sidebar', to: 'head/sidebar.js'
@@ -0,0 +1,61 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Head
4
+ class Active
5
+ include Calls
6
+
7
+ option :url
8
+ option :current_path
9
+ option :condition
10
+
11
+ def call
12
+ :'is-active' if active?
13
+ end
14
+
15
+ private
16
+
17
+ def linked_path
18
+ ::URI.parse(url).path
19
+ end
20
+
21
+ def active?
22
+ return false if url == '#'
23
+
24
+ # Adapted from https://github.com/comfy/active_link_to (MIT license)
25
+ case condition
26
+
27
+ when :inclusive, nil # default
28
+ !current_path.match(%r{^#{Regexp.escape(linked_path).chomp('/')}(/.*|\?.*)?$}).blank?
29
+
30
+ when :exclusive
31
+ !current_path.match(%r{^#{Regexp.escape(linked_path)}/?(\?.*)?$}).blank?
32
+
33
+ when :exact
34
+ current_path == linked_path
35
+
36
+ when Regexp
37
+ !current_path.match(condition).blank?
38
+
39
+ when Array
40
+ controllers = [*condition[0]]
41
+ actions = [*condition[1]]
42
+ ((controllers.blank? || controllers.member?(params[:controller])) &&
43
+ (actions.blank? || actions.member?(params[:action]))) ||
44
+ controllers.any? do |controller, action|
45
+ params[:controller] == controller.to_s && params[:action] == action.to_s
46
+ end
47
+
48
+ when TrueClass
49
+ true
50
+
51
+ when FalseClass
52
+ false
53
+
54
+ when Hash
55
+ condition.all? do |key, value|
56
+ params[key].to_s == value.to_s
57
+ end
58
+ end
59
+ end
60
+ end
61
+ end
data/lib/head/version.rb CHANGED
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Head
4
- VERSION = '0.0.1'
4
+ VERSION = '0.0.3'
5
5
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: head
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.1
4
+ version: 0.0.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - halo
@@ -118,11 +118,13 @@ files:
118
118
  - LICENSE.txt
119
119
  - README.md
120
120
  - app/assets/fonts/head/headicons.woff
121
- - app/assets/fonts/icomoon.json
121
+ - app/assets/fonts/head/icomoon.json
122
122
  - app/assets/javascript/head/index.js
123
123
  - app/assets/javascript/head/knob.js
124
+ - app/assets/javascript/head/sidebar.js
124
125
  - app/assets/javascript/head/wing.js
125
126
  - app/assets/stylesheets/head/components/knob.sass
127
+ - app/assets/stylesheets/head/components/sidebar.sass
126
128
  - app/assets/stylesheets/head/components/theater.sass
127
129
  - app/assets/stylesheets/head/components/wing.sass
128
130
  - app/assets/stylesheets/head/generics/flip.sass
@@ -131,7 +133,7 @@ files:
131
133
  - app/assets/stylesheets/head/objects/headicon.sass
132
134
  - app/assets/stylesheets/head/package.json
133
135
  - app/assets/stylesheets/head/settings/_colors.sass
134
- - app/assets/stylesheets/head/settings/_icons.scss
136
+ - app/assets/stylesheets/head/settings/_headicons.scss
135
137
  - app/assets/stylesheets/head/tools/_cloud.sass
136
138
  - app/assets/stylesheets/head/tools/_link.sass
137
139
  - app/assets/stylesheets/head/tools/_mandatory.sass
@@ -140,11 +142,16 @@ files:
140
142
  - app/assets/stylesheets/head/utilities/smokescreen.sass
141
143
  - app/components/head/application_component.rb
142
144
  - app/components/head/knob.rb
145
+ - app/components/head/sidebar.rb
146
+ - app/components/head/sidebars/category.rb
147
+ - app/components/head/sidebars/headline.rb
148
+ - app/components/head/sidebars/link.rb
143
149
  - app/components/head/theater.rb
144
150
  - app/components/head/wing.rb
145
151
  - config/importmap.rb
146
152
  - config/locales/head.en.yml
147
153
  - lib/head.rb
154
+ - lib/head/active.rb
148
155
  - lib/head/css.rb
149
156
  - lib/head/engine.rb
150
157
  - lib/head/identicon.rb