@port60/template-kit 0.20.1 → 0.20.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.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@port60/template-kit",
3
- "version": "0.20.1",
3
+ "version": "0.20.3",
4
4
  "description": "Build Port60 site templates locally: scaffold, live-preview, validate against the platform contract, and package for studio upload. AI-agent ready: every scaffold ships AGENTS.md and validate emits machine-readable JSON.",
5
5
  "type": "module",
6
6
  "bin": {
@@ -191,7 +191,7 @@
191
191
  "name": "search",
192
192
  "label": "Site search",
193
193
  "status": "available",
194
- "description": "Searches published articles, programmes, events and public resources. It reads public projections only and cannot search member, payment, private media or admin data.",
194
+ "description": "The site's search box: a typeahead over the platform's search index (articles, events, services, campaigns, appeals, volunteering and public documents; published and live rows only, never member, payment, private media or admin data). Suggestions are the things themselves, grouped by kind, each a direct link, with a matched-text line when the hit was in the body; Enter or the last row goes to the platform's /search results page. An accessible combobox: the active suggestion carries is-active. Where the box sits is the template's decision.",
195
195
  "params": [],
196
196
  "stylingApi": [
197
197
  ".site-search",
@@ -205,7 +205,11 @@
205
205
  ".site-search-kind",
206
206
  ".site-search-link",
207
207
  ".site-search-summary",
208
- ".site-search-empty"
208
+ ".site-search-empty",
209
+ ".site-search-title",
210
+ ".site-search-context",
211
+ ".site-search-more",
212
+ ".site-search-corrected"
209
213
  ]
210
214
  },
211
215
  {
@@ -4732,3 +4732,239 @@ textarea.p60-form-control {
4732
4732
  justify-content: center;
4733
4733
  text-align: center;
4734
4734
  }
4735
+
4736
+ /* ---- Site search (docs/search.md) ----
4737
+ The typeahead island (a template places it; the platform styles the box and its suggestions)
4738
+ and the platform's /search results page. Suggestions are a listbox under the box: the kind
4739
+ label, the title, a date or place, and the matched-text line with the hit words emphasised. */
4740
+ .site-search {
4741
+ position: relative;
4742
+ }
4743
+ .site-search-form {
4744
+ margin: 0;
4745
+ }
4746
+ .site-search-label {
4747
+ position: absolute;
4748
+ width: 1px;
4749
+ height: 1px;
4750
+ overflow: hidden;
4751
+ clip: rect(0 0 0 0);
4752
+ white-space: nowrap;
4753
+ }
4754
+ .site-search-fields {
4755
+ display: flex;
4756
+ align-items: center;
4757
+ gap: 0.4rem;
4758
+ }
4759
+ .site-search-input {
4760
+ min-width: 12rem;
4761
+ padding: 0.55rem 0.95rem;
4762
+ border-radius: 999px;
4763
+ }
4764
+ /* Named in every theme: the placeholder is the theme's ink at half strength, never the generic
4765
+ muted grey, which vanishes on a dark masthead. */
4766
+ .site-search-input::placeholder {
4767
+ color: color-mix(in srgb, var(--ink) 55%, transparent);
4768
+ opacity: 1;
4769
+ }
4770
+ .site-search-submit {
4771
+ padding: 0.55rem 0.95rem;
4772
+ border: 1px solid var(--line);
4773
+ border-radius: 999px;
4774
+ background: var(--surface);
4775
+ color: var(--ink);
4776
+ font-weight: 600;
4777
+ cursor: pointer;
4778
+ }
4779
+ .site-search-submit:hover {
4780
+ background: var(--bg-tint);
4781
+ }
4782
+ .site-search-results {
4783
+ position: absolute;
4784
+ top: 100%;
4785
+ left: 0;
4786
+ z-index: 70;
4787
+ min-width: min(26rem, calc(100vw - 2rem));
4788
+ max-height: 70vh;
4789
+ overflow: auto;
4790
+ margin: 0.35rem 0 0;
4791
+ padding: 0.4rem;
4792
+ list-style: none;
4793
+ background: var(--surface);
4794
+ border: 1px solid var(--line);
4795
+ border-radius: 14px;
4796
+ box-shadow: var(--shadow);
4797
+ text-align: left;
4798
+ }
4799
+ .site-search-link {
4800
+ display: grid;
4801
+ grid-template-columns: auto 1fr;
4802
+ column-gap: 0.6rem;
4803
+ row-gap: 0.15rem;
4804
+ align-items: baseline;
4805
+ padding: 0.55rem 0.65rem;
4806
+ border-radius: 10px;
4807
+ color: var(--ink);
4808
+ font-weight: 500;
4809
+ }
4810
+ .site-search-result.is-active .site-search-link,
4811
+ .site-search-link:hover {
4812
+ background: var(--bg-tint);
4813
+ }
4814
+ .site-search-kind {
4815
+ font-size: 0.72rem;
4816
+ font-weight: 700;
4817
+ letter-spacing: 0.04em;
4818
+ text-transform: uppercase;
4819
+ color: var(--muted);
4820
+ }
4821
+ .site-search-title {
4822
+ font-weight: 600;
4823
+ }
4824
+ .site-search-context,
4825
+ .site-search-summary {
4826
+ grid-column: 2;
4827
+ font-size: 0.85rem;
4828
+ font-weight: 400;
4829
+ color: var(--muted);
4830
+ }
4831
+ .site-search-summary mark {
4832
+ background: transparent;
4833
+ color: var(--ink);
4834
+ font-weight: 700;
4835
+ }
4836
+ .site-search-more .site-search-link {
4837
+ grid-template-columns: 1fr;
4838
+ color: var(--primary);
4839
+ font-weight: 600;
4840
+ }
4841
+ .site-search-empty,
4842
+ .site-search-corrected {
4843
+ position: absolute;
4844
+ top: 100%;
4845
+ left: 0;
4846
+ z-index: 70;
4847
+ min-width: min(26rem, calc(100vw - 2rem));
4848
+ margin: 0.35rem 0 0;
4849
+ padding: 0.65rem 0.8rem;
4850
+ background: var(--surface);
4851
+ border: 1px solid var(--line);
4852
+ border-radius: 14px;
4853
+ box-shadow: var(--shadow);
4854
+ font-size: 0.9rem;
4855
+ color: var(--muted);
4856
+ text-align: left;
4857
+ }
4858
+ .site-search-corrected {
4859
+ top: auto;
4860
+ bottom: 100%;
4861
+ margin: 0 0 0.35rem;
4862
+ }
4863
+ /* In the primary nav the box stays compact and grows on focus; Enter searches, so the button rests. */
4864
+ /* In a header nav the box is compact and grows on focus; the submit button is the Enter key.
4865
+ Keyed off default's .site-nav AND the layout behaviour API's #site-nav (in attribute form on
4866
+ purpose: class-level specificity, so a template can still override with two classes of its own),
4867
+ so every artifact template's primary nav gets the same compact box whatever its class is called. */
4868
+ .site-nav .site-search,
4869
+ [id="site-nav"] .site-search {
4870
+ margin-inline-start: 0.35rem;
4871
+ }
4872
+ .site-nav .site-search-input,
4873
+ [id="site-nav"] .site-search-input {
4874
+ width: 9rem;
4875
+ min-width: 0;
4876
+ padding: 0.45rem 0.85rem;
4877
+ font-size: 0.92rem;
4878
+ transition: width 0.16s ease;
4879
+ }
4880
+ .site-nav .site-search-input:focus,
4881
+ [id="site-nav"] .site-search-input:focus {
4882
+ width: 12.5rem;
4883
+ }
4884
+ .site-nav .site-search-submit,
4885
+ [id="site-nav"] .site-search-submit {
4886
+ display: none;
4887
+ }
4888
+ .site-nav .site-search-results,
4889
+ [id="site-nav"] .site-search-results,
4890
+ .site-nav .site-search-empty,
4891
+ [id="site-nav"] .site-search-empty,
4892
+ .site-nav .site-search-corrected,
4893
+ [id="site-nav"] .site-search-corrected {
4894
+ right: 0;
4895
+ left: auto;
4896
+ }
4897
+ @media (max-width: 860px) {
4898
+ .site-nav .site-search,
4899
+ [id="site-nav"] .site-search {
4900
+ margin: 0.5rem 0;
4901
+ }
4902
+ .site-nav .site-search-input,
4903
+ [id="site-nav"] .site-search-input,
4904
+ .site-nav .site-search-input:focus,
4905
+ [id="site-nav"] .site-search-input:focus {
4906
+ width: 100%;
4907
+ }
4908
+ .site-nav .site-search-results,
4909
+ [id="site-nav"] .site-search-results,
4910
+ .site-nav .site-search-empty,
4911
+ [id="site-nav"] .site-search-empty,
4912
+ .site-nav .site-search-corrected,
4913
+ [id="site-nav"] .site-search-corrected {
4914
+ position: static;
4915
+ min-width: 0;
4916
+ box-shadow: none;
4917
+ }
4918
+ }
4919
+
4920
+ /* The results page: breadcrumb rows, full width like every page body. */
4921
+ .search-hits {
4922
+ margin: 1rem 0 0;
4923
+ padding: 0;
4924
+ list-style: none;
4925
+ }
4926
+ .search-hit {
4927
+ padding: 1rem 0;
4928
+ border-bottom: 1px solid var(--line);
4929
+ }
4930
+ .search-hit-crumb {
4931
+ display: block;
4932
+ font-size: 0.8rem;
4933
+ font-weight: 700;
4934
+ letter-spacing: 0.04em;
4935
+ text-transform: uppercase;
4936
+ color: var(--muted);
4937
+ }
4938
+ .search-hit-title {
4939
+ display: inline-block;
4940
+ margin-top: 0.2rem;
4941
+ font-size: 1.15rem;
4942
+ font-weight: 600;
4943
+ color: var(--primary);
4944
+ }
4945
+ .search-hit-title:hover {
4946
+ text-decoration: underline;
4947
+ }
4948
+ .search-hit-snippet {
4949
+ margin: 0.35rem 0 0;
4950
+ color: var(--muted);
4951
+ }
4952
+ .search-hit-snippet mark {
4953
+ background: transparent;
4954
+ color: var(--ink);
4955
+ font-weight: 700;
4956
+ }
4957
+ .search-corrected,
4958
+ .search-empty {
4959
+ color: var(--muted);
4960
+ }
4961
+ .search-filters {
4962
+ margin-top: 1rem;
4963
+ }
4964
+ .search-page-box {
4965
+ max-width: 40rem;
4966
+ margin: 1rem 0 1.5rem;
4967
+ }
4968
+ .search-page-box .site-search-input {
4969
+ flex: 1 1 auto;
4970
+ }
@@ -3,7 +3,7 @@
3
3
  chrome classes (.site-header/.site-nav/…) so the base mechanics (sticky header, burger
4
4
  breakpoint, dropdown hover) apply, and emits the documented behaviour attributes
5
5
  (data-nav-burger, #site-nav) so the platform tail script wires the mobile burger. Identity is
6
- PLACED, never rebuilt: {% island 'member_menu' %}. The footer derives everything from brand/nav, no fabricated copy (derive or omit).
6
+ PLACED, never rebuilt: {% island 'member_menu' %} and {% island 'search' %}. The footer derives everything from brand/nav, no fabricated copy (derive or omit).
7
7
  {% endcomment %}
8
8
  <header class="site-header">
9
9
  <div class="container header-inner">
@@ -42,6 +42,7 @@
42
42
  <a href="{{ item.href }}"{% if item.external %} target="_blank" rel="noopener"{% endif %}>{{ item.label }}</a>
43
43
  {% endif %}
44
44
  {% endfor %}
45
+ {% island 'search' %}
45
46
  {% island 'member_menu' %}
46
47
  </nav>
47
48
  </div>
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "starter",
3
- "version": "1.12.0",
3
+ "version": "1.13.0",
4
4
  "format": "port60-liquid@1",
5
5
  "label": "Starter",
6
6
  "description": "The reference template for the Port60 dialect, the developer docs' worked example and the base to copy when building your own. 1.1.0 adds the layout slot: the template owns the header, navigation and footer chrome.",
@@ -23,7 +23,8 @@
23
23
  "member_menu",
24
24
  "hero_carousel",
25
25
  "map",
26
- "primary_action_widget"
26
+ "primary_action_widget",
27
+ "search"
27
28
  ],
28
29
  "layout": true,
29
30
  "heroImagery": true,
@@ -53,7 +54,7 @@
53
54
  }
54
55
  ]
55
56
  },
56
- "changelog": "Adds the impact map section: pin your located work on a themed map of where you work.",
57
+ "changelog": "Places the site search box in the header: a typeahead across events, articles, services, campaigns, appeals, volunteering and documents, with the results page at /search.",
57
58
  "imagery": {
58
59
  "hero": {
59
60
  "idealAspect": "16:9",